pull/3338/head
Jamie Rees 5 years ago
commit bea8551cd3

@ -1,6 +1,77 @@
# Changelog # Changelog
## v3.0.4817 (2019-10-15) ## (unreleased)
### **New Features**
- Update login.component.ts. [Jamie]
- Update CHANGELOG.md. [Jamie]
- Updated SlackNotification.cs. [Tim]
### **Fixes**
- Fixed the issue where we couldn't always pick up stuff on the sync. [tidusjar]
- Removed hangfire completly from Ombi. [tidusjar]
- Fixed the notifications issue. [tidusjar]
- Fixed the issues where the DB was being disposed too early. [tidusjar]
- Fixed an error with the newsletter with the new db structure. [tidusjar]
- Output some useful stuff to the about window regarding the databases. [tidusjar]
- Fixed the migration for combined databases. [tidusjar]
- Fixed the issue where exisitng databases would now fail due to the DB structure changes. [tidusjar]
- Finished it! [tidusjar]
- Got MySql working. [tidusjar]
- Got the new DB structure in place. [tidusjar]
- Fix for #3219. [tidusjar]
- Fixed the error in the newsletter. [tidusjar]
- Fixed #3208. [tidusjar]
- Use tags and autocomplete for excluded keywords. [Taylor Buchanan]
- Add comments to clarify filter decisions. [Taylor Buchanan]
- Fix TS import order. [Taylor Buchanan]
- Add adult movie filtering. [Taylor Buchanan]
- Fix search bar overlap on mobile. [Taylor Buchanan]
- New translations en.json (Slovak) [Jamie]
- New translations en.json (Slovak) [Jamie]
- New translations en.json (Slovak) [Jamie]
- New translations en.json (Slovak) [Jamie]
- New translations en.json (Slovak) [Jamie]
- New translations en.json (Slovak) [Jamie]
- New translations en.json (Slovak) [Jamie]
- Add SK lang. [Jamie Rees]
- Add the migration to the correct database... #3214. [tidusjar]
- Hopefully provide a fix now for #2998 Theory is that the refresh metadata was using stale data and then overriding the availbility that just happened on that media item. [tidusjar]
## v3.0.4817 (2019-10-12)
### **New Features** ### **New Features**
@ -34,6 +105,8 @@
### **Fixes** ### **Fixes**
- Gitchangelog. [tidusjar]
- Fixed #3078. [tidusjar] - Fixed #3078. [tidusjar]
- Fixes issue #3195 The new string extension method ToHttpsUrl ensures that URLs starting with "https" are no longer turned into "httpss" The commit also replaces all occurances of the error prone .Replace("http", "https") in the whole solution. [msdeibel] - Fixes issue #3195 The new string extension method ToHttpsUrl ensures that URLs starting with "https" are no longer turned into "httpss" The commit also replaces all occurances of the error prone .Replace("http", "https") in the whole solution. [msdeibel]

@ -189,11 +189,7 @@ namespace Ombi.Core.Engine
var requests = await (OrderMovies(allRequests, orderFilter.OrderType)).Skip(position).Take(count) var requests = await (OrderMovies(allRequests, orderFilter.OrderType)).Skip(position).Take(count)
.ToListAsync(); .ToListAsync();
requests.ForEach(async x => await CheckForSubscription(shouldHide, requests);
{
x.PosterPath = PosterPathHelper.FixPosterPath(x.PosterPath);
await CheckForSubscription(shouldHide, x);
});
return new RequestsViewModel<MovieRequests> return new RequestsViewModel<MovieRequests>
{ {
Collection = requests, Collection = requests,
@ -236,11 +232,8 @@ namespace Ombi.Core.Engine
var total = await allRequests.CountAsync(); var total = await allRequests.CountAsync();
var requests = await allRequests.Skip(position).Take(count) var requests = await allRequests.Skip(position).Take(count)
.ToListAsync(); .ToListAsync();
requests.ForEach(async x =>
{ await CheckForSubscription(shouldHide, requests);
x.PosterPath = PosterPathHelper.FixPosterPath(x.PosterPath);
await CheckForSubscription(shouldHide, x);
});
return new RequestsViewModel<MovieRequests> return new RequestsViewModel<MovieRequests>
{ {
Collection = requests, Collection = requests,
@ -282,11 +275,8 @@ namespace Ombi.Core.Engine
var total = await allRequests.CountAsync(); var total = await allRequests.CountAsync();
var requests = await allRequests.Skip(position).Take(count) var requests = await allRequests.Skip(position).Take(count)
.ToListAsync(); .ToListAsync();
requests.ForEach(async x =>
{ await CheckForSubscription(shouldHide, requests);
x.PosterPath = PosterPathHelper.FixPosterPath(x.PosterPath);
await CheckForSubscription(shouldHide, x);
});
return new RequestsViewModel<MovieRequests> return new RequestsViewModel<MovieRequests>
{ {
Collection = requests, Collection = requests,
@ -369,35 +359,38 @@ namespace Ombi.Core.Engine
allRequests = await MovieRepository.GetWithUser().ToListAsync(); allRequests = await MovieRepository.GetWithUser().ToListAsync();
} }
allRequests.ForEach(async x => await CheckForSubscription(shouldHide, allRequests);
{
x.PosterPath = PosterPathHelper.FixPosterPath(x.PosterPath);
await CheckForSubscription(shouldHide, x);
});
return allRequests; return allRequests;
} }
public async Task<MovieRequests> GetRequest(int requestId) public async Task<MovieRequests> GetRequest(int requestId)
{ {
var request = await MovieRepository.GetWithUser().Where(x => x.Id == requestId).FirstOrDefaultAsync(); var request = await MovieRepository.GetWithUser().Where(x => x.Id == requestId).FirstOrDefaultAsync();
request.PosterPath = PosterPathHelper.FixPosterPath(request.PosterPath); await CheckForSubscription(new HideResult(), new List<MovieRequests>{request });
await CheckForSubscription(new HideResult(), request);
return request; return request;
} }
private async Task CheckForSubscription(HideResult shouldHide, MovieRequests x) private async Task CheckForSubscription(HideResult shouldHide, List<MovieRequests> movieRequests)
{ {
if (shouldHide.UserId == x.RequestedUserId) var requestIds = movieRequests.Select(x => x.Id);
{ var sub = await _subscriptionRepository.GetAll().Where(s =>
x.ShowSubscribe = false; s.UserId == shouldHide.UserId && requestIds.Contains(s.RequestId) && s.RequestType == RequestType.Movie)
} .ToListAsync();
else foreach (var x in movieRequests)
{ {
x.ShowSubscribe = true; x.PosterPath = PosterPathHelper.FixPosterPath(x.PosterPath);
var sub = await _subscriptionRepository.GetAll().FirstOrDefaultAsync(s => if (shouldHide.UserId == x.RequestedUserId)
s.UserId == shouldHide.UserId && s.RequestId == x.Id && s.RequestType == RequestType.Movie); {
x.Subscribed = sub != null; x.ShowSubscribe = false;
}
else
{
x.ShowSubscribe = true;
var hasSub = sub.FirstOrDefault(r => r.RequestId == x.Id);
x.Subscribed = hasSub != null;
}
} }
} }
@ -420,11 +413,8 @@ namespace Ombi.Core.Engine
} }
var results = allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase)).ToList(); var results = allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase)).ToList();
results.ForEach(async x => await CheckForSubscription(shouldHide, results);
{
x.PosterPath = PosterPathHelper.FixPosterPath(x.PosterPath);
await CheckForSubscription(shouldHide, x);
});
return results; return results;
} }
@ -448,7 +438,7 @@ namespace Ombi.Core.Engine
request.Denied = true; request.Denied = true;
request.DeniedReason = denyReason; request.DeniedReason = denyReason;
// We are denying a request // We are denying a request
NotificationHelper.Notify(request, NotificationType.RequestDeclined); await NotificationHelper.Notify(request, NotificationType.RequestDeclined);
await MovieRepository.Update(request); await MovieRepository.Update(request);
return new RequestEngineResult return new RequestEngineResult
@ -476,7 +466,7 @@ namespace Ombi.Core.Engine
var canNotify = await RunSpecificRule(request, SpecificRules.CanSendNotification); var canNotify = await RunSpecificRule(request, SpecificRules.CanSendNotification);
if (canNotify.Success) if (canNotify.Success)
{ {
NotificationHelper.Notify(request, NotificationType.RequestApproved); await NotificationHelper.Notify(request, NotificationType.RequestApproved);
} }
if (request.Approved) if (request.Approved)
@ -592,7 +582,7 @@ namespace Ombi.Core.Engine
request.Available = true; request.Available = true;
request.MarkedAsAvailable = DateTime.Now; request.MarkedAsAvailable = DateTime.Now;
NotificationHelper.Notify(request, NotificationType.RequestAvailable); await NotificationHelper.Notify(request, NotificationType.RequestAvailable);
await MovieRepository.Update(request); await MovieRepository.Update(request);
return new RequestEngineResult return new RequestEngineResult
@ -608,8 +598,8 @@ namespace Ombi.Core.Engine
var result = await RunSpecificRule(model, SpecificRules.CanSendNotification); var result = await RunSpecificRule(model, SpecificRules.CanSendNotification);
if (result.Success) if (result.Success)
{ {
NotificationHelper.NewRequest(model); await NotificationHelper.NewRequest(model);
} }
await _requestLog.Add(new RequestLog await _requestLog.Add(new RequestLog

@ -320,7 +320,7 @@ namespace Ombi.Core.Engine
request.Denied = true; request.Denied = true;
request.DeniedReason = reason; request.DeniedReason = reason;
// We are denying a request // We are denying a request
NotificationHelper.Notify(request, NotificationType.RequestDeclined); await NotificationHelper.Notify(request, NotificationType.RequestDeclined);
await MusicRepository.Update(request); await MusicRepository.Update(request);
return new RequestEngineResult return new RequestEngineResult
@ -348,7 +348,7 @@ namespace Ombi.Core.Engine
var canNotify = await RunSpecificRule(request, SpecificRules.CanSendNotification); var canNotify = await RunSpecificRule(request, SpecificRules.CanSendNotification);
if (canNotify.Success) if (canNotify.Success)
{ {
NotificationHelper.Notify(request, NotificationType.RequestApproved); await NotificationHelper.Notify(request, NotificationType.RequestApproved);
} }
if (request.Approved) if (request.Approved)
@ -475,7 +475,7 @@ namespace Ombi.Core.Engine
request.Available = true; request.Available = true;
request.MarkedAsAvailable = DateTime.Now; request.MarkedAsAvailable = DateTime.Now;
NotificationHelper.Notify(request, NotificationType.RequestAvailable); await NotificationHelper.Notify(request, NotificationType.RequestAvailable);
await MusicRepository.Update(request); await MusicRepository.Update(request);
return new RequestEngineResult return new RequestEngineResult
@ -492,7 +492,7 @@ namespace Ombi.Core.Engine
var result = await RunSpecificRule(model, SpecificRules.CanSendNotification); var result = await RunSpecificRule(model, SpecificRules.CanSendNotification);
if (result.Success) if (result.Success)
{ {
NotificationHelper.NewRequest(model); await NotificationHelper.NewRequest(model);
} }
await _requestLog.Add(new RequestLog await _requestLog.Add(new RequestLog

@ -159,8 +159,7 @@ namespace Ombi.Core.Engine
.Skip(position).Take(count).ToListAsync(); .Skip(position).Take(count).ToListAsync();
} }
await CheckForSubscription(shouldHide, allRequests);
allRequests.ForEach(async r => { await CheckForSubscription(shouldHide, r); });
return new RequestsViewModel<TvRequests> return new RequestsViewModel<TvRequests>
{ {
@ -195,7 +194,8 @@ namespace Ombi.Core.Engine
{ {
return new RequestsViewModel<TvRequests>(); return new RequestsViewModel<TvRequests>();
} }
allRequests.ForEach(async r => { await CheckForSubscription(shouldHide, r); });
await CheckForSubscription(shouldHide, allRequests);
return new RequestsViewModel<TvRequests> return new RequestsViewModel<TvRequests>
{ {
@ -217,7 +217,7 @@ namespace Ombi.Core.Engine
allRequests = await TvRepository.Get().ToListAsync(); allRequests = await TvRepository.Get().ToListAsync();
} }
allRequests.ForEach(async r => { await CheckForSubscription(shouldHide, r); }); await CheckForSubscription(shouldHide, allRequests);
return allRequests; return allRequests;
} }
@ -262,7 +262,8 @@ namespace Ombi.Core.Engine
allRequests = sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase) allRequests = sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase)
? allRequests.OrderBy(x => prop.GetValue(x)).ToList() ? allRequests.OrderBy(x => prop.GetValue(x)).ToList()
: allRequests.OrderByDescending(x => prop.GetValue(x)).ToList(); : allRequests.OrderByDescending(x => prop.GetValue(x)).ToList();
allRequests.ForEach(async r => { await CheckForSubscription(shouldHide, r); });
await CheckForSubscription(shouldHide, allRequests);
// Make sure we do not show duplicate child requests // Make sure we do not show duplicate child requests
allRequests = allRequests.DistinctBy(x => x.ParentRequest.Title).ToList(); allRequests = allRequests.DistinctBy(x => x.ParentRequest.Title).ToList();
@ -315,7 +316,7 @@ namespace Ombi.Core.Engine
allRequests = sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase) allRequests = sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase)
? allRequests.OrderBy(x => prop.GetValue(x)).ToList() ? allRequests.OrderBy(x => prop.GetValue(x)).ToList()
: allRequests.OrderByDescending(x => prop.GetValue(x)).ToList(); : allRequests.OrderByDescending(x => prop.GetValue(x)).ToList();
allRequests.ForEach(async r => { await CheckForSubscription(shouldHide, r); }); await CheckForSubscription(shouldHide, allRequests);
// Make sure we do not show duplicate child requests // Make sure we do not show duplicate child requests
allRequests = allRequests.DistinctBy(x => x.ParentRequest.Title).ToList(); allRequests = allRequests.DistinctBy(x => x.ParentRequest.Title).ToList();
@ -344,7 +345,7 @@ namespace Ombi.Core.Engine
allRequests = await TvRepository.GetLite().ToListAsync(); allRequests = await TvRepository.GetLite().ToListAsync();
} }
allRequests.ForEach(async r => { await CheckForSubscription(shouldHide, r); }); await CheckForSubscription(shouldHide, allRequests);
return allRequests; return allRequests;
} }
@ -363,7 +364,7 @@ namespace Ombi.Core.Engine
request = await TvRepository.Get().Where(x => x.Id == requestId).FirstOrDefaultAsync(); request = await TvRepository.Get().Where(x => x.Id == requestId).FirstOrDefaultAsync();
} }
await CheckForSubscription(shouldHide, request); await CheckForSubscription(shouldHide, new List<TvRequests>{request});
return request; return request;
} }
@ -417,7 +418,7 @@ namespace Ombi.Core.Engine
allRequests = await TvRepository.GetChild().Include(x => x.SeasonRequests).Where(x => x.ParentRequestId == tvId).ToListAsync(); allRequests = await TvRepository.GetChild().Include(x => x.SeasonRequests).Where(x => x.ParentRequestId == tvId).ToListAsync();
} }
allRequests.ForEach(async r => { await CheckForSubscription(shouldHide, r); }); await CheckForSubscription(shouldHide, allRequests);
return allRequests; return allRequests;
} }
@ -436,7 +437,7 @@ namespace Ombi.Core.Engine
} }
var results = await allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase)).ToListAsync(); var results = await allRequests.Where(x => x.Title.Contains(search, CompareOptions.IgnoreCase)).ToListAsync();
results.ForEach(async r => { await CheckForSubscription(shouldHide, r); }); await CheckForSubscription(shouldHide, results);
return results; return results;
} }
@ -501,7 +502,7 @@ namespace Ombi.Core.Engine
if (request.Approved) if (request.Approved)
{ {
NotificationHelper.Notify(request, NotificationType.RequestApproved); await NotificationHelper.Notify(request, NotificationType.RequestApproved);
// Autosend // Autosend
await TvSender.Send(request); await TvSender.Send(request);
} }
@ -524,7 +525,7 @@ namespace Ombi.Core.Engine
request.Denied = true; request.Denied = true;
request.DeniedReason = reason; request.DeniedReason = reason;
await TvRepository.UpdateChild(request); await TvRepository.UpdateChild(request);
NotificationHelper.Notify(request, NotificationType.RequestDeclined); await NotificationHelper.Notify(request, NotificationType.RequestDeclined);
return new RequestEngineResult return new RequestEngineResult
{ {
Result = true Result = true
@ -533,7 +534,7 @@ namespace Ombi.Core.Engine
public async Task<ChildRequests> UpdateChildRequest(ChildRequests request) public async Task<ChildRequests> UpdateChildRequest(ChildRequests request)
{ {
await TvRepository.UpdateChild(request); await TvRepository.UpdateChild(request);
return request; return request;
} }
@ -551,14 +552,14 @@ namespace Ombi.Core.Engine
// Delete the parent // Delete the parent
TvRepository.Db.TvRequests.Remove(parent); TvRepository.Db.TvRequests.Remove(parent);
} }
await TvRepository.Db.SaveChangesAsync(); await TvRepository.Db.SaveChangesAsync();
} }
public async Task RemoveTvRequest(int requestId) public async Task RemoveTvRequest(int requestId)
{ {
var request = await TvRepository.Get().FirstOrDefaultAsync(x => x.Id == requestId); var request = await TvRepository.Get().FirstOrDefaultAsync(x => x.Id == requestId);
await TvRepository.Delete(request); await TvRepository.Delete(request);
} }
public async Task<bool> UserHasRequest(string userId) public async Task<bool> UserHasRequest(string userId)
@ -612,7 +613,7 @@ namespace Ombi.Core.Engine
} }
} }
await TvRepository.UpdateChild(request); await TvRepository.UpdateChild(request);
NotificationHelper.Notify(request, NotificationType.RequestAvailable); await NotificationHelper.Notify(request, NotificationType.RequestAvailable);
return new RequestEngineResult return new RequestEngineResult
{ {
Result = true, Result = true,
@ -633,26 +634,32 @@ namespace Ombi.Core.Engine
} }
} }
private async Task CheckForSubscription(HideResult shouldHide, TvRequests x) private async Task CheckForSubscription(HideResult shouldHide, List<TvRequests> x)
{ {
foreach (var tv in x.ChildRequests) foreach (var tvRequest in x)
{ {
await CheckForSubscription(shouldHide, tv); await CheckForSubscription(shouldHide, tvRequest.ChildRequests);
} }
} }
private async Task CheckForSubscription(HideResult shouldHide, ChildRequests x) private async Task CheckForSubscription(HideResult shouldHide, List<ChildRequests> childRequests)
{ {
if (shouldHide.UserId == x.RequestedUserId) var sub = _subscriptionRepository.GetAll();
var childIds = childRequests.Select(x => x.Id);
var relevantSubs = await sub.Where(s =>
s.UserId == shouldHide.UserId && childIds.Contains(s.Id) && s.RequestType == RequestType.TvShow).ToListAsync();
foreach (var x in childRequests)
{ {
x.ShowSubscribe = false; if (shouldHide.UserId == x.RequestedUserId)
} {
else x.ShowSubscribe = false;
{ }
x.ShowSubscribe = true; else
var sub = await _subscriptionRepository.GetAll().FirstOrDefaultAsync(s => {
s.UserId == shouldHide.UserId && s.RequestId == x.Id && s.RequestType == RequestType.TvShow); x.ShowSubscribe = true;
x.Subscribed = sub != null; var result = relevantSubs.FirstOrDefault(s => s.RequestId == x.Id);
x.Subscribed = result != null;
}
} }
} }
@ -691,7 +698,7 @@ namespace Ombi.Core.Engine
var sendRuleResult = await RunSpecificRule(model, SpecificRules.CanSendNotification); var sendRuleResult = await RunSpecificRule(model, SpecificRules.CanSendNotification);
if (sendRuleResult.Success) if (sendRuleResult.Success)
{ {
NotificationHelper.NewRequest(model); await NotificationHelper.NewRequest(model);
} }
await _requestLog.Add(new RequestLog await _requestLog.Add(new RequestLog
@ -706,7 +713,7 @@ namespace Ombi.Core.Engine
if (model.Approved) if (model.Approved)
{ {
// Autosend // Autosend
NotificationHelper.Notify(model, NotificationType.RequestApproved); await NotificationHelper.Notify(model, NotificationType.RequestApproved);
var result = await TvSender.Send(model); var result = await TvSender.Send(model);
if (result.Success) if (result.Success)
{ {

@ -1,5 +1,6 @@
using System; using System;
using Hangfire; using System.Collections.Generic;
using System.Threading.Tasks;
using Ombi.Core.Notifications; using Ombi.Core.Notifications;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Notifications.Models; using Ombi.Notifications.Models;
@ -9,13 +10,7 @@ namespace Ombi.Core
{ {
public class NotificationHelper : INotificationHelper public class NotificationHelper : INotificationHelper
{ {
public NotificationHelper(INotificationService service) public async Task NewRequest(FullBaseRequest model)
{
NotificationService = service;
}
private INotificationService NotificationService { get; }
public void NewRequest(FullBaseRequest model)
{ {
var notificationModel = new NotificationOptions var notificationModel = new NotificationOptions
{ {
@ -24,11 +19,13 @@ namespace Ombi.Core
NotificationType = NotificationType.NewRequest, NotificationType = NotificationType.NewRequest,
RequestType = model.RequestType RequestType = model.RequestType
}; };
BackgroundJob.Enqueue(() => NotificationService.Publish(notificationModel)); await OmbiQuartz.TriggerJob(nameof(INotificationService), "Notifications", new Dictionary<string, object>
{
{JobDataKeys.NotificationOptions, notificationModel}
});
} }
public void NewRequest(ChildRequests model) public async Task NewRequest(ChildRequests model)
{ {
var notificationModel = new NotificationOptions var notificationModel = new NotificationOptions
{ {
@ -36,11 +33,14 @@ namespace Ombi.Core
DateTime = DateTime.Now, DateTime = DateTime.Now,
NotificationType = NotificationType.NewRequest, NotificationType = NotificationType.NewRequest,
RequestType = model.RequestType RequestType = model.RequestType
}; };
BackgroundJob.Enqueue(() => NotificationService.Publish(notificationModel)); await OmbiQuartz.TriggerJob(nameof(INotificationService), "Notifications", new Dictionary<string, object>
{
{JobDataKeys.NotificationOptions, notificationModel}
});
} }
public void NewRequest(AlbumRequest model) public async Task NewRequest(AlbumRequest model)
{ {
var notificationModel = new NotificationOptions var notificationModel = new NotificationOptions
{ {
@ -48,12 +48,15 @@ namespace Ombi.Core
DateTime = DateTime.Now, DateTime = DateTime.Now,
NotificationType = NotificationType.NewRequest, NotificationType = NotificationType.NewRequest,
RequestType = model.RequestType RequestType = model.RequestType
}; };
BackgroundJob.Enqueue(() => NotificationService.Publish(notificationModel)); await OmbiQuartz.TriggerJob(nameof(INotificationService), "Notifications", new Dictionary<string, object>
{
{JobDataKeys.NotificationOptions, notificationModel}
});
} }
public void Notify(MovieRequests model, NotificationType type) public async Task Notify(MovieRequests model, NotificationType type)
{ {
var notificationModel = new NotificationOptions var notificationModel = new NotificationOptions
{ {
@ -63,10 +66,13 @@ namespace Ombi.Core
RequestType = model.RequestType, RequestType = model.RequestType,
Recipient = model.RequestedUser?.Email ?? string.Empty Recipient = model.RequestedUser?.Email ?? string.Empty
}; };
BackgroundJob.Enqueue(() => NotificationService.Publish(notificationModel)); await OmbiQuartz.TriggerJob(nameof(INotificationService), "Notifications", new Dictionary<string, object>
{
{JobDataKeys.NotificationOptions, notificationModel}
});
} }
public void Notify(ChildRequests model, NotificationType type) public async Task Notify(ChildRequests model, NotificationType type)
{ {
var notificationModel = new NotificationOptions var notificationModel = new NotificationOptions
{ {
@ -76,10 +82,13 @@ namespace Ombi.Core
RequestType = model.RequestType, RequestType = model.RequestType,
Recipient = model.RequestedUser?.Email ?? string.Empty Recipient = model.RequestedUser?.Email ?? string.Empty
}; };
BackgroundJob.Enqueue(() => NotificationService.Publish(notificationModel)); await OmbiQuartz.TriggerJob(nameof(INotificationService), "Notifications", new Dictionary<string, object>
{
{JobDataKeys.NotificationOptions, notificationModel}
});
} }
public void Notify(AlbumRequest model, NotificationType type) public async Task Notify(AlbumRequest model, NotificationType type)
{ {
var notificationModel = new NotificationOptions var notificationModel = new NotificationOptions
{ {
@ -90,7 +99,18 @@ namespace Ombi.Core
Recipient = model.RequestedUser?.Email ?? string.Empty Recipient = model.RequestedUser?.Email ?? string.Empty
}; };
BackgroundJob.Enqueue(() => NotificationService.Publish(notificationModel)); await OmbiQuartz.TriggerJob(nameof(INotificationService), "Notifications", new Dictionary<string, object>
{
{JobDataKeys.NotificationOptions, notificationModel}
});
}
public async Task Notify(NotificationOptions model)
{
await OmbiQuartz.TriggerJob(nameof(INotificationService), "Notifications", new Dictionary<string, object>
{
{JobDataKeys.NotificationOptions, model}
});
} }
} }
} }

@ -11,7 +11,6 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="AutoMapper" Version="6.1.1" /> <PackageReference Include="AutoMapper" Version="6.1.1" />
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="3.2.0" /> <PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="3.2.0" />
<PackageReference Include="Hangfire" Version="1.7.0" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="2.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.4" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.4" />
<PackageReference Include="MusicBrainzAPI" Version="2.0.1" /> <PackageReference Include="MusicBrainzAPI" Version="2.0.1" />

@ -1,16 +1,19 @@
using Ombi.Core.Models.Requests; using System.Threading.Tasks;
using Ombi.Core.Models.Requests;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Notifications.Models;
using Ombi.Store.Entities.Requests; using Ombi.Store.Entities.Requests;
namespace Ombi.Core namespace Ombi.Core
{ {
public interface INotificationHelper public interface INotificationHelper
{ {
void NewRequest(FullBaseRequest model); Task NewRequest(FullBaseRequest model);
void NewRequest(ChildRequests model); Task NewRequest(ChildRequests model);
void NewRequest(AlbumRequest model); Task NewRequest(AlbumRequest model);
void Notify(MovieRequests model, NotificationType type); Task Notify(MovieRequests model, NotificationType type);
void Notify(ChildRequests model, NotificationType type); Task Notify(ChildRequests model, NotificationType type);
void Notify(AlbumRequest model, NotificationType type); Task Notify(AlbumRequest model, NotificationType type);
Task Notify(NotificationOptions model);
} }
} }

@ -95,7 +95,7 @@ namespace Ombi.Core.Senders
Type = RequestType.Movie, Type = RequestType.Movie,
RetryCount = 0 RetryCount = 0
}); });
_notificationHelper.Notify(model, NotificationType.ItemAddedToFaultQueue); await _notificationHelper.Notify(model, NotificationType.ItemAddedToFaultQueue);
} }
} }

@ -65,7 +65,7 @@ namespace Ombi.Core.Senders
Type = RequestType.Album, Type = RequestType.Album,
RetryCount = 0 RetryCount = 0
}); });
_notificationHelper.Notify(model, NotificationType.ItemAddedToFaultQueue); await _notificationHelper.Notify(model, NotificationType.ItemAddedToFaultQueue);
} }
} }

@ -128,7 +128,7 @@ namespace Ombi.Core.Senders
Type = RequestType.TvShow, Type = RequestType.TvShow,
RetryCount = 0 RetryCount = 0
}); });
_notificationHelper.Notify(model, NotificationType.ItemAddedToFaultQueue); await _notificationHelper.Notify(model, NotificationType.ItemAddedToFaultQueue);
} }
} }

@ -1,6 +1,5 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Security.Principal; using System.Security.Principal;
using Hangfire;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
@ -197,8 +196,8 @@ namespace Ombi.DependencyInjection
public static void RegisterJobs(this IServiceCollection services) public static void RegisterJobs(this IServiceCollection services)
{ {
services.AddSingleton<IJobFactory, IoCJobFactory>(provider => new IoCJobFactory(provider)); services.AddSingleton<QuartzJobRunner>();
services.AddTransient<IBackgroundJobClient, BackgroundJobClient>(); services.AddSingleton<IJobFactory, IoCJobFactory>();
services.AddTransient<IPlexContentSync, PlexContentSync>(); services.AddTransient<IPlexContentSync, PlexContentSync>();
services.AddTransient<IEmbyContentSync, EmbyContentSync>(); services.AddTransient<IEmbyContentSync, EmbyContentSync>();

@ -39,6 +39,8 @@ namespace Ombi.Helpers.Tests
yield return new TestCaseData("com.plexapp.agents.agent47://tt2543456?lang=en", ProviderIdType.Imdb).Returns("tt2543456").SetName("Unknown IMDB agent"); yield return new TestCaseData("com.plexapp.agents.agent47://tt2543456?lang=en", ProviderIdType.Imdb).Returns("tt2543456").SetName("Unknown IMDB agent");
yield return new TestCaseData("com.plexapp.agents.agent47://456822/1/1?lang=en", ProviderIdType.TvDb).Returns("456822").SetName("Unknown TvDb agent"); yield return new TestCaseData("com.plexapp.agents.agent47://456822/1/1?lang=en", ProviderIdType.TvDb).Returns("456822").SetName("Unknown TvDb agent");
yield return new TestCaseData("com.plexapp.agents.agent47://456822/999/999?lang=en", ProviderIdType.TvDb).Returns("456822").SetName("Unknown TvDb agent, large episode and season"); yield return new TestCaseData("com.plexapp.agents.agent47://456822/999/999?lang=en", ProviderIdType.TvDb).Returns("456822").SetName("Unknown TvDb agent, large episode and season");
yield return new TestCaseData("com.plexapp.agents.xbmcnfotv://153021/2/1?lang=xn", ProviderIdType.TvDb).Returns("153021").SetName("xmbc agent, tv episode");
yield return new TestCaseData("com.plexapp.agents.xbmcnfotv://153021?lang=xn", ProviderIdType.TvDb).Returns("153021").SetName("xmbc agent, tv show");
} }
} }

@ -1,7 +1,8 @@
namespace Ombi.Schedule namespace Ombi.Helpers
{ {
public class JobDataKeys public class JobDataKeys
{ {
public const string RecentlyAddedSearch = "recentlyAddedSearch"; public const string RecentlyAddedSearch = "recentlyAddedSearch";
public const string NotificationOptions = nameof(NotificationOptions);
} }
} }

@ -14,6 +14,7 @@
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
<PackageReference Include="Nito.AsyncEx" Version="5.0.0-pre-05" /> <PackageReference Include="Nito.AsyncEx" Version="5.0.0-pre-05" />
<PackageReference Include="Quartz" Version="3.0.7" />
<PackageReference Include="System.Security.Claims" Version="4.3.0" /> <PackageReference Include="System.Security.Claims" Version="4.3.0" />
</ItemGroup> </ItemGroup>

@ -1,11 +1,10 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Ombi.Helpers;
using Quartz; using Quartz;
using Quartz.Impl; using Quartz.Impl;
using Quartz.Spi; using Quartz.Spi;
namespace Ombi.Schedule namespace Ombi.Helpers
{ {
public class OmbiQuartz public class OmbiQuartz
{ {
@ -78,7 +77,12 @@ namespace Ombi.Schedule
{ {
await Scheduler.TriggerJob(new JobKey(jobName, group)); await Scheduler.TriggerJob(new JobKey(jobName, group));
} }
public static async Task TriggerJob(string jobName, string group, IDictionary<string, object> data)
{
await Scheduler.TriggerJob(new JobKey(jobName, group), new JobDataMap(data));
}
public static async Task Start() public static async Task Start()
{ {
await Scheduler.Start(); await Scheduler.Start();

@ -33,14 +33,15 @@ namespace Ombi.Helpers
{ {
public class PlexHelper public class PlexHelper
{ {
private const string ImdbMatchExpression = "tt([0-9]{1,10})"; private const string ImdbMatchExpression = "tt([0-9]{1,10})";
private const string TvDbIdMatchExpression = "//[0-9]+/([0-9]{1,3})/([0-9]{1,3})"; private const string TvDbIdMatchExpression = "//[0-9]+/?([0-9]{1,3})/?([0-9]{1,3})";
public static ProviderId GetProviderIdFromPlexGuid(string guid) public static ProviderId GetProviderIdFromPlexGuid(string guid)
{ {
//com.plexapp.agents.thetvdb://269586/2/8?lang=en //com.plexapp.agents.thetvdb://269586/2/8?lang=en
//com.plexapp.agents.themoviedb://390043?lang=en //com.plexapp.agents.themoviedb://390043?lang=en
//com.plexapp.agents.imdb://tt2543164?lang=en //com.plexapp.agents.imdb://tt2543164?lang=en
// https://github.com/tidusjar/Ombi/issues/3277
if (string.IsNullOrEmpty(guid)) if (string.IsNullOrEmpty(guid))
{ {
return new ProviderId(); return new ProviderId();
@ -55,7 +56,7 @@ namespace Ombi.Helpers
{ {
TheTvDb = guidSplit[1] TheTvDb = guidSplit[1]
}; };
} else }
if (guid.Contains("themoviedb", CompareOptions.IgnoreCase)) if (guid.Contains("themoviedb", CompareOptions.IgnoreCase))
{ {
return new ProviderId return new ProviderId
@ -63,7 +64,6 @@ namespace Ombi.Helpers
TheMovieDb = guidSplit[1] TheMovieDb = guidSplit[1]
}; };
} }
else
if (guid.Contains("imdb", CompareOptions.IgnoreCase)) if (guid.Contains("imdb", CompareOptions.IgnoreCase))
{ {
return new ProviderId return new ProviderId
@ -71,72 +71,29 @@ namespace Ombi.Helpers
ImdbId = guidSplit[1] ImdbId = guidSplit[1]
}; };
} }
else
var imdbRegex = new Regex(ImdbMatchExpression, RegexOptions.Compiled);
var tvdbRegex = new Regex(TvDbIdMatchExpression, RegexOptions.Compiled);
var imdbMatch = imdbRegex.IsMatch(guid);
if (imdbMatch)
{ {
var imdbRegex = new Regex(ImdbMatchExpression, RegexOptions.Compiled); return new ProviderId
var tvdbRegex = new Regex(TvDbIdMatchExpression, RegexOptions.Compiled);
var imdbMatch = imdbRegex.IsMatch(guid);
if (imdbMatch)
{
return new ProviderId
{
ImdbId = guidSplit[1]
};
}
else
{ {
// Check if it matches the TvDb pattern ImdbId = guidSplit[1]
var tvdbMatch = tvdbRegex.IsMatch(guid); };
if (tvdbMatch)
{
return new ProviderId
{
TheTvDb = guidSplit[1]
};
}
}
} }
}
return new ProviderId();
}
public static EpisodeModelHelper GetSeasonsAndEpisodesFromPlexGuid(string guid) // Check if it matches the TvDb pattern
{ var tvdbMatch = tvdbRegex.IsMatch(guid);
var ep = new EpisodeModelHelper(); if (tvdbMatch)
//com.plexapp.agents.thetvdb://269586/2/8?lang=en
//com.plexapp.agents.themoviedb://390043?lang=en
//com.plexapp.agents.imdb://tt2543164?lang=en
if (string.IsNullOrEmpty(guid))
return null;
try
{
var guidSplit = guid.Split(new[] { '/', '?' }, StringSplitOptions.RemoveEmptyEntries);
if (guidSplit.Length > 2)
{ {
if (guid.Contains("thetvdb", CompareOptions.IgnoreCase)) return new ProviderId
{
ep.ProviderId = new ProviderId {TheTvDb = guidSplit[1]};
}
if (guid.Contains("themoviedb", CompareOptions.IgnoreCase))
{
ep.ProviderId = new ProviderId { TheMovieDb = guidSplit[1] };
}
if (guid.Contains("imdb", CompareOptions.IgnoreCase))
{ {
ep.ProviderId = new ProviderId { ImdbId = guidSplit[1] }; TheTvDb = guidSplit[1]
};
}
ep.SeasonNumber = int.Parse(guidSplit[2]);
ep.EpisodeNumber = int.Parse(guidSplit[3]);
} }
return ep;
}
catch (Exception)
{
return ep;
} }
return new ProviderId();
} }
public static string GetPlexMediaUrl(string machineId, int mediaId) public static string GetPlexMediaUrl(string machineId, int mediaId)
@ -147,13 +104,6 @@ namespace Ombi.Helpers
} }
} }
public class EpisodeModelHelper
{
public ProviderId ProviderId { get; set; }
public int SeasonNumber { get; set; }
public int EpisodeNumber { get; set; }
}
public class ProviderId public class ProviderId
{ {
public string TheTvDb { get; set; } public string TheTvDb { get; set; }

@ -1,13 +1,12 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Ombi.Notifications; using Ombi.Notifications;
using Ombi.Notifications.Models; using Ombi.Notifications.Models;
using Quartz;
namespace Ombi.Core.Notifications namespace Ombi.Core.Notifications
{ {
public interface INotificationService public interface INotificationService : IJob
{ {
Task Publish(NotificationOptions model);
Task Publish(NotificationOptions model, Ombi.Settings.Settings.Models.Settings settings);
Task PublishTest(NotificationOptions model, Ombi.Settings.Settings.Models.Settings settings, INotification type);
} }
} }

@ -7,78 +7,46 @@ using Microsoft.Extensions.Logging;
using Ombi.Core.Notifications; using Ombi.Core.Notifications;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Notifications.Models; using Ombi.Notifications.Models;
using Quartz;
namespace Ombi.Notifications namespace Ombi.Notifications
{ {
public class NotificationService : INotificationService public class NotificationService : INotificationService
{ {
private readonly IServiceProvider _provider;
public NotificationService(IServiceProvider provider, ILogger<NotificationService> log) public NotificationService(IServiceProvider provider, ILogger<NotificationService> log)
{ {
_provider = provider;
Log = log; Log = log;
NotificationAgents = new List<INotification>(); NotificationAgents = new List<INotification>();
PopulateAgents();
var baseSearchType = typeof(BaseNotification<>).Name;
var ass = typeof(NotificationService).GetTypeInfo().Assembly;
foreach (var ti in ass.DefinedTypes)
{
if (ti?.BaseType?.Name == baseSearchType)
{
var type = ti?.AsType();
var ctors = type.GetConstructors();
var ctor = ctors.FirstOrDefault();
var services = new List<object>();
foreach (var param in ctor.GetParameters())
{
services.Add(provider.GetService(param.ParameterType));
}
var item = Activator.CreateInstance(type, services.ToArray());
NotificationAgents.Add((INotification)item);
}
}
} }
private List<INotification> NotificationAgents { get; } private List<INotification> NotificationAgents { get; }
private ILogger<NotificationService> Log { get; } private ILogger<NotificationService> Log { get; }
/// <summary>^ /// <summary>
/// Sends a notification to the user. This one is used in normal notification scenarios /// Sends a notification to the user. This one is used in normal notification scenarios
/// </summary> /// </summary>
/// <param name="model">The model.</param> /// <param name="context">The model.</param>
/// <returns></returns> /// <returns></returns>
public async Task Publish(NotificationOptions model) public async Task Execute(IJobExecutionContext context)
{ {
var notificationTasks = new List<Task>(); JobDataMap dataMap = context.MergedJobDataMap;
var model = (NotificationOptions)dataMap.Get(JobDataKeys.NotificationOptions);
foreach (var agent in NotificationAgents) foreach (var agent in NotificationAgents)
{ {
notificationTasks.Add(NotifyAsync(agent,model)); await NotifyAsync(agent, model);
} }
await Task.WhenAll(notificationTasks).ConfigureAwait(false);
} }
/// <summary>
/// Sends a notification to the user, this is usually for testing the settings.
/// </summary>
/// <param name="model">The model.</param>
/// <param name="settings">The settings.</param>
/// <returns></returns>
public async Task Publish(NotificationOptions model, Settings.Settings.Models.Settings settings)
{
var notificationTasks = NotificationAgents.Select(notification => NotifyAsync(notification, model, settings));
await Task.WhenAll(notificationTasks).ConfigureAwait(false);
}
private async Task NotifyAsync(INotification notification, NotificationOptions model) private async Task NotifyAsync(INotification notification, NotificationOptions model)
{ {
try try
{ {
await notification.NotifyAsync(model).ConfigureAwait(false); await notification.NotifyAsync(model);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -86,26 +54,31 @@ namespace Ombi.Notifications
} }
} }
private async Task NotifyAsync(INotification notification, NotificationOptions model, Ombi.Settings.Settings.Models.Settings settings) private void PopulateAgents()
{ {
if (model.RequestId == 0) var baseSearchType = typeof(BaseNotification<>).Name;
{
throw new ArgumentException("RequestId is not set"); var ass = typeof(NotificationService).GetTypeInfo().Assembly;
}
try foreach (var ti in ass.DefinedTypes)
{
await notification.NotifyAsync(model, settings).ConfigureAwait(false);
}
catch (Exception ex)
{ {
throw new InvalidOperationException(ex.Message); if (ti?.BaseType?.Name == baseSearchType)
} {
} var type = ti?.AsType();
var ctors = type.GetConstructors();
var ctor = ctors.FirstOrDefault();
public async Task PublishTest(NotificationOptions model, Ombi.Settings.Settings.Models.Settings settings, INotification type) var services = new List<object>();
{ foreach (var param in ctor.GetParameters())
await type.NotifyAsync(model, settings); {
services.Add(_provider.GetService(param.ParameterType));
}
var item = Activator.CreateInstance(type, services.ToArray());
NotificationAgents.Add((INotification)item);
}
}
} }
} }
} }

@ -3,6 +3,7 @@ using NUnit.Framework;
using Quartz; using Quartz;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Ombi.Helpers;
namespace Ombi.Schedule.Tests namespace Ombi.Schedule.Tests
{ {

@ -5,11 +5,11 @@ using System.Linq.Expressions;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Castle.Components.DictionaryAdapter; using Castle.Components.DictionaryAdapter;
using Hangfire;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
using Moq; using Moq;
using MockQueryable.Moq; using MockQueryable.Moq;
using NUnit.Framework; using NUnit.Framework;
using Ombi.Core;
using Ombi.Core.Notifications; using Ombi.Core.Notifications;
using Ombi.Hubs; using Ombi.Hubs;
using Ombi.Schedule.Jobs.Plex; using Ombi.Schedule.Jobs.Plex;
@ -30,19 +30,19 @@ namespace Ombi.Schedule.Tests
_repo = new Mock<IPlexContentRepository>(); _repo = new Mock<IPlexContentRepository>();
_tv = new Mock<ITvRequestRepository>(); _tv = new Mock<ITvRequestRepository>();
_movie = new Mock<IMovieRequestRepository>(); _movie = new Mock<IMovieRequestRepository>();
_notify = new Mock<INotificationService>(); _notify = new Mock<INotificationHelper>();
var hub = new Mock<IHubContext<NotificationHub>>(); var hub = new Mock<IHubContext<NotificationHub>>();
hub.Setup(x => hub.Setup(x =>
x.Clients.Clients(It.IsAny<IReadOnlyList<string>>()).SendCoreAsync(It.IsAny<string>(), It.IsAny<object[]>(), It.IsAny<CancellationToken>())); x.Clients.Clients(It.IsAny<IReadOnlyList<string>>()).SendCoreAsync(It.IsAny<string>(), It.IsAny<object[]>(), It.IsAny<CancellationToken>()));
NotificationHub.UsersOnline.TryAdd("A", new HubUsers()); NotificationHub.UsersOnline.TryAdd("A", new HubUsers());
Checker = new PlexAvailabilityChecker(_repo.Object, _tv.Object, _movie.Object, _notify.Object, new Mock<IBackgroundJobClient>().Object, null, hub.Object); Checker = new PlexAvailabilityChecker(_repo.Object, _tv.Object, _movie.Object, _notify.Object, null, hub.Object);
} }
private Mock<IPlexContentRepository> _repo; private Mock<IPlexContentRepository> _repo;
private Mock<ITvRequestRepository> _tv; private Mock<ITvRequestRepository> _tv;
private Mock<IMovieRequestRepository> _movie; private Mock<IMovieRequestRepository> _movie;
private Mock<INotificationService> _notify; private Mock<INotificationHelper> _notify;
private PlexAvailabilityChecker Checker; private PlexAvailabilityChecker Checker;
[Test] [Test]

@ -1,28 +0,0 @@
using System;
using System.Linq;
using System.Reflection;
using Hangfire;
using Microsoft.Extensions.DependencyInjection;
namespace Ombi.Schedule
{
public class IoCJobActivator : JobActivator
{
private readonly IServiceProvider _container;
public IoCJobActivator(IServiceProvider container)
{
_container = container;
}
public override object ActivateJob(Type type)
{
var scopeFactory = _container.GetService<IServiceScopeFactory>();
var scope = scopeFactory.CreateScope();
var scopedContainer = scope.ServiceProvider;
var interfaceType = type.GetTypeInfo().ImplementedInterfaces.FirstOrDefault();
var implementation = scopedContainer.GetRequiredService(interfaceType);
return implementation;
}
}
}

@ -7,26 +7,18 @@ namespace Ombi.Schedule
{ {
public class IoCJobFactory : IJobFactory public class IoCJobFactory : IJobFactory
{ {
private readonly IServiceProvider _factory; private readonly IServiceProvider _serviceProvider;
public IoCJobFactory(IServiceProvider serviceProvider)
public IoCJobFactory(IServiceProvider factory)
{ {
_factory = factory; _serviceProvider = serviceProvider;
} }
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler) public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{ {
var scopeFactory = _factory.GetService<IServiceScopeFactory>(); return _serviceProvider.GetRequiredService<QuartzJobRunner>();
var scope = scopeFactory.CreateScope();
var scopedContainer = scope.ServiceProvider;
var implementation = scopedContainer.GetRequiredService(bundle.JobDetail.JobType) as IJob;
return implementation;
} }
public void ReturnJob(IJob job) public void ReturnJob(IJob job)
{ {
var disposable = job as IDisposable;
disposable?.Dispose();
} }
} }
} }

@ -28,10 +28,10 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Hangfire;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ombi.Core;
using Ombi.Core.Notifications; using Ombi.Core.Notifications;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Hubs; using Ombi.Hubs;
@ -47,7 +47,7 @@ namespace Ombi.Schedule.Jobs.Emby
public class EmbyAvaliabilityChecker : IEmbyAvaliabilityChecker public class EmbyAvaliabilityChecker : IEmbyAvaliabilityChecker
{ {
public EmbyAvaliabilityChecker(IEmbyContentRepository repo, ITvRequestRepository t, IMovieRequestRepository m, public EmbyAvaliabilityChecker(IEmbyContentRepository repo, ITvRequestRepository t, IMovieRequestRepository m,
INotificationService n, ILogger<EmbyAvaliabilityChecker> log, IHubContext<NotificationHub> notification) INotificationHelper n, ILogger<EmbyAvaliabilityChecker> log, IHubContext<NotificationHub> notification)
{ {
_repo = repo; _repo = repo;
_tvRepo = t; _tvRepo = t;
@ -60,7 +60,7 @@ namespace Ombi.Schedule.Jobs.Emby
private readonly ITvRequestRepository _tvRepo; private readonly ITvRequestRepository _tvRepo;
private readonly IMovieRequestRepository _movieRepo; private readonly IMovieRequestRepository _movieRepo;
private readonly IEmbyContentRepository _repo; private readonly IEmbyContentRepository _repo;
private readonly INotificationService _notificationService; private readonly INotificationHelper _notificationService;
private readonly ILogger<EmbyAvaliabilityChecker> _log; private readonly ILogger<EmbyAvaliabilityChecker> _log;
private readonly IHubContext<NotificationHub> _notification; private readonly IHubContext<NotificationHub> _notification;
@ -109,14 +109,14 @@ namespace Ombi.Schedule.Jobs.Emby
_log.LogDebug("MovieId: {0}, RequestUser: {1}", movie.Id, recipient); _log.LogDebug("MovieId: {0}, RequestUser: {1}", movie.Id, recipient);
BackgroundJob.Enqueue(() => _notificationService.Publish(new NotificationOptions await _notificationService.Notify(new NotificationOptions
{ {
DateTime = DateTime.Now, DateTime = DateTime.Now,
NotificationType = NotificationType.RequestAvailable, NotificationType = NotificationType.RequestAvailable,
RequestId = movie.Id, RequestId = movie.Id,
RequestType = RequestType.Movie, RequestType = RequestType.Movie,
Recipient = recipient, Recipient = recipient,
})); });
} }
} }
await _movieRepo.Save(); await _movieRepo.Save();
@ -200,14 +200,14 @@ namespace Ombi.Schedule.Jobs.Emby
// We have fulfulled this request! // We have fulfulled this request!
child.Available = true; child.Available = true;
child.MarkedAsAvailable = DateTime.Now; child.MarkedAsAvailable = DateTime.Now;
BackgroundJob.Enqueue(() => _notificationService.Publish(new NotificationOptions await _notificationService.Notify(new NotificationOptions
{ {
DateTime = DateTime.Now, DateTime = DateTime.Now,
NotificationType = NotificationType.RequestAvailable, NotificationType = NotificationType.RequestAvailable,
RequestId = child.Id, RequestId = child.Id,
RequestType = RequestType.TvShow, RequestType = RequestType.TvShow,
Recipient = child.RequestedUser.Email Recipient = child.RequestedUser.Email
})); });
} }
} }
@ -222,7 +222,6 @@ namespace Ombi.Schedule.Jobs.Emby
if (disposing) if (disposing)
{ {
_movieRepo?.Dispose();
} }
_disposed = true; _disposed = true;
} }

@ -2,7 +2,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Hangfire;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ombi.Api.Emby; using Ombi.Api.Emby;
@ -15,7 +14,6 @@ using Ombi.Schedule.Jobs.Ombi;
using Ombi.Store.Entities; using Ombi.Store.Entities;
using Ombi.Store.Repository; using Ombi.Store.Repository;
using Quartz; using Quartz;
using Serilog;
using EmbyMediaType = Ombi.Store.Entities.EmbyMediaType; using EmbyMediaType = Ombi.Store.Entities.EmbyMediaType;
namespace Ombi.Schedule.Jobs.Emby namespace Ombi.Schedule.Jobs.Emby
@ -217,7 +215,6 @@ namespace Ombi.Schedule.Jobs.Emby
if (disposing) if (disposing)
{ {
_settings?.Dispose(); _settings?.Dispose();
_repo?.Dispose();
} }
_disposed = true; _disposed = true;
} }

@ -29,13 +29,13 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Hangfire;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ombi.Api.Emby; using Ombi.Api.Emby;
using Ombi.Core.Settings; using Ombi.Core.Settings;
using Ombi.Core.Settings.Models.External; using Ombi.Core.Settings.Models.External;
using Ombi.Hubs; using Ombi.Hubs;
using Ombi.Helpers;
using Ombi.Store.Entities; using Ombi.Store.Entities;
using Ombi.Store.Repository; using Ombi.Store.Repository;
using Quartz; using Quartz;
@ -165,7 +165,6 @@ namespace Ombi.Schedule.Jobs.Emby
if (disposing) if (disposing)
{ {
_settings?.Dispose(); _settings?.Dispose();
_repo?.Dispose();
} }
_disposed = true; _disposed = true;
} }

@ -1,7 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Hangfire;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Internal;
@ -21,14 +20,12 @@ namespace Ombi.Schedule.Jobs.Lidarr
public class LidarrAlbumSync : ILidarrAlbumSync public class LidarrAlbumSync : ILidarrAlbumSync
{ {
public LidarrAlbumSync(ISettingsService<LidarrSettings> lidarr, ILidarrApi lidarrApi, ILogger<LidarrAlbumSync> log, ExternalContext ctx, public LidarrAlbumSync(ISettingsService<LidarrSettings> lidarr, ILidarrApi lidarrApi, ILogger<LidarrAlbumSync> log, ExternalContext ctx,
IBackgroundJobClient job, ILidarrAvailabilityChecker availability, IHubContext<NotificationHub> notification) IHubContext<NotificationHub> notification)
{ {
_lidarrSettings = lidarr; _lidarrSettings = lidarr;
_lidarrApi = lidarrApi; _lidarrApi = lidarrApi;
_logger = log; _logger = log;
_ctx = ctx; _ctx = ctx;
_job = job;
_availability = availability;
_notification = notification; _notification = notification;
} }
@ -36,8 +33,6 @@ namespace Ombi.Schedule.Jobs.Lidarr
private readonly ILidarrApi _lidarrApi; private readonly ILidarrApi _lidarrApi;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly ExternalContext _ctx; private readonly ExternalContext _ctx;
private readonly IBackgroundJobClient _job;
private readonly ILidarrAvailabilityChecker _availability;
private readonly IHubContext<NotificationHub> _notification; private readonly IHubContext<NotificationHub> _notification;
public async Task Execute(IJobExecutionContext ctx) public async Task Execute(IJobExecutionContext ctx)

@ -1,7 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Hangfire;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Internal;

@ -2,11 +2,10 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Hangfire;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ombi.Core.Notifications; using Ombi.Core;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Hubs; using Ombi.Hubs;
using Ombi.Notifications.Models; using Ombi.Notifications.Models;
@ -21,12 +20,11 @@ namespace Ombi.Schedule.Jobs.Lidarr
public class LidarrAvailabilityChecker : ILidarrAvailabilityChecker public class LidarrAvailabilityChecker : ILidarrAvailabilityChecker
{ {
public LidarrAvailabilityChecker(IMusicRequestRepository requests, IRepository<LidarrAlbumCache> albums, ILogger<LidarrAvailabilityChecker> log, public LidarrAvailabilityChecker(IMusicRequestRepository requests, IRepository<LidarrAlbumCache> albums, ILogger<LidarrAvailabilityChecker> log,
IBackgroundJobClient job, INotificationService notification, IHubContext<NotificationHub> notificationHub) INotificationHelper notification, IHubContext<NotificationHub> notificationHub)
{ {
_cachedAlbums = albums; _cachedAlbums = albums;
_requestRepository = requests; _requestRepository = requests;
_logger = log; _logger = log;
_job = job;
_notificationService = notification; _notificationService = notification;
_notification = notificationHub; _notification = notificationHub;
} }
@ -34,8 +32,7 @@ namespace Ombi.Schedule.Jobs.Lidarr
private readonly IMusicRequestRepository _requestRepository; private readonly IMusicRequestRepository _requestRepository;
private readonly IRepository<LidarrAlbumCache> _cachedAlbums; private readonly IRepository<LidarrAlbumCache> _cachedAlbums;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IBackgroundJobClient _job; private readonly INotificationHelper _notificationService;
private readonly INotificationService _notificationService;
private readonly IHubContext<NotificationHub> _notification; private readonly IHubContext<NotificationHub> _notification;
public async Task Execute(IJobExecutionContext ctx) public async Task Execute(IJobExecutionContext ctx)
@ -67,14 +64,15 @@ namespace Ombi.Schedule.Jobs.Lidarr
_logger.LogDebug("AlbumId: {0}, RequestUser: {1}", albumRequest.Id, recipient); _logger.LogDebug("AlbumId: {0}, RequestUser: {1}", albumRequest.Id, recipient);
_job.Enqueue(() => _notificationService.Publish(new NotificationOptions
await _notificationService.Notify(new NotificationOptions
{ {
DateTime = DateTime.Now, DateTime = DateTime.Now,
NotificationType = NotificationType.RequestAvailable, NotificationType = NotificationType.RequestAvailable,
RequestId = albumRequest.Id, RequestId = albumRequest.Id,
RequestType = RequestType.Album, RequestType = RequestType.Album,
Recipient = recipient, Recipient = recipient,
})); });
} }
await _notification.Clients.Clients(NotificationHub.AdminConnectionIds) await _notification.Clients.Clients(NotificationHub.AdminConnectionIds)

@ -1,5 +1,4 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Hangfire.Server;
namespace Ombi.Schedule.Jobs.Ombi namespace Ombi.Schedule.Jobs.Ombi
{ {

@ -50,7 +50,6 @@ namespace Ombi.Schedule.Jobs.Ombi
if (disposing) if (disposing)
{ {
_issuesRepository?.Dispose();
_settings?.Dispose(); _settings?.Dispose();
} }
_disposed = true; _disposed = true;

@ -1,8 +1,6 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Hangfire;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ombi.Api.Plex;
using Ombi.Core.Settings; using Ombi.Core.Settings;
using Ombi.Core.Settings.Models.External; using Ombi.Core.Settings.Models.External;
using Ombi.Helpers; using Ombi.Helpers;
@ -99,7 +97,6 @@ namespace Ombi.Schedule.Jobs.Ombi
if (disposing) if (disposing)
{ {
_plexRepo?.Dispose();
_settings?.Dispose(); _settings?.Dispose();
} }
_disposed = true; _disposed = true;

@ -39,7 +39,7 @@ namespace Ombi.Schedule.Jobs.Ombi
IMovieDbApi movieApi, ITvMazeApi tvApi, IEmailProvider email, ISettingsService<CustomizationSettings> custom, IMovieDbApi movieApi, ITvMazeApi tvApi, IEmailProvider email, ISettingsService<CustomizationSettings> custom,
ISettingsService<EmailNotificationSettings> emailSettings, INotificationTemplatesRepository templateRepo, ISettingsService<EmailNotificationSettings> emailSettings, INotificationTemplatesRepository templateRepo,
UserManager<OmbiUser> um, ISettingsService<NewsletterSettings> newsletter, ILogger<NewsletterJob> log, UserManager<OmbiUser> um, ISettingsService<NewsletterSettings> newsletter, ILogger<NewsletterJob> log,
ILidarrApi lidarrApi, IRepository<LidarrAlbumCache> albumCache, ISettingsService<LidarrSettings> lidarrSettings, ILidarrApi lidarrApi, IExternalRepository<LidarrAlbumCache> albumCache, ISettingsService<LidarrSettings> lidarrSettings,
ISettingsService<OmbiSettings> ombiSettings, ISettingsService<PlexSettings> plexSettings, ISettingsService<EmbySettings> embySettings ISettingsService<OmbiSettings> ombiSettings, ISettingsService<PlexSettings> plexSettings, ISettingsService<EmbySettings> embySettings
, IHubContext<NotificationHub> notification) , IHubContext<NotificationHub> notification)
{ {
@ -82,7 +82,7 @@ namespace Ombi.Schedule.Jobs.Ombi
private readonly UserManager<OmbiUser> _userManager; private readonly UserManager<OmbiUser> _userManager;
private readonly ILogger _log; private readonly ILogger _log;
private readonly ILidarrApi _lidarrApi; private readonly ILidarrApi _lidarrApi;
private readonly IRepository<LidarrAlbumCache> _lidarrAlbumRepository; private readonly IExternalRepository<LidarrAlbumCache> _lidarrAlbumRepository;
private readonly ISettingsService<LidarrSettings> _lidarrSettings; private readonly ISettingsService<LidarrSettings> _lidarrSettings;
private readonly ISettingsService<PlexSettings> _plexSettings; private readonly ISettingsService<PlexSettings> _plexSettings;
private readonly ISettingsService<EmbySettings> _embySettings; private readonly ISettingsService<EmbySettings> _embySettings;
@ -945,12 +945,9 @@ namespace Ombi.Schedule.Jobs.Ombi
if (disposing) if (disposing)
{ {
_plex?.Dispose();
_emby?.Dispose();
_newsletterSettings?.Dispose(); _newsletterSettings?.Dispose();
_customizationSettings?.Dispose(); _customizationSettings?.Dispose();
_emailSettings.Dispose(); _emailSettings.Dispose();
_recentlyAddedLog.Dispose();
_templateRepo?.Dispose(); _templateRepo?.Dispose();
_userManager?.Dispose(); _userManager?.Dispose();
} }

@ -9,8 +9,6 @@ using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Hangfire;
using Hangfire.Server;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ombi.Core.Processor; using Ombi.Core.Processor;
using Ombi.Core.Settings; using Ombi.Core.Settings;

@ -1,8 +1,6 @@
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Hangfire;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ombi.Api.Emby; using Ombi.Api.Emby;
@ -365,8 +363,6 @@ namespace Ombi.Schedule.Jobs.Ombi
if (disposing) if (disposing)
{ {
_plexRepo?.Dispose();
_embyRepo?.Dispose();
_plexSettings?.Dispose(); _plexSettings?.Dispose();
} }
_disposed = true; _disposed = true;

@ -1,12 +1,10 @@
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Hangfire;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ombi.Core.Notifications; using Ombi.Core;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Hubs; using Ombi.Hubs;
using Ombi.Notifications.Models; using Ombi.Notifications.Models;
@ -21,13 +19,12 @@ namespace Ombi.Schedule.Jobs.Plex
public class PlexAvailabilityChecker : IPlexAvailabilityChecker public class PlexAvailabilityChecker : IPlexAvailabilityChecker
{ {
public PlexAvailabilityChecker(IPlexContentRepository repo, ITvRequestRepository tvRequest, IMovieRequestRepository movies, public PlexAvailabilityChecker(IPlexContentRepository repo, ITvRequestRepository tvRequest, IMovieRequestRepository movies,
INotificationService notification, IBackgroundJobClient background, ILogger<PlexAvailabilityChecker> log, IHubContext<NotificationHub> hub) INotificationHelper notification, ILogger<PlexAvailabilityChecker> log, IHubContext<NotificationHub> hub)
{ {
_tvRepo = tvRequest; _tvRepo = tvRequest;
_repo = repo; _repo = repo;
_movieRepo = movies; _movieRepo = movies;
_notificationService = notification; _notificationService = notification;
_backgroundJobClient = background;
_log = log; _log = log;
_notification = hub; _notification = hub;
} }
@ -35,8 +32,7 @@ namespace Ombi.Schedule.Jobs.Plex
private readonly ITvRequestRepository _tvRepo; private readonly ITvRequestRepository _tvRepo;
private readonly IMovieRequestRepository _movieRepo; private readonly IMovieRequestRepository _movieRepo;
private readonly IPlexContentRepository _repo; private readonly IPlexContentRepository _repo;
private readonly INotificationService _notificationService; private readonly INotificationHelper _notificationService;
private readonly IBackgroundJobClient _backgroundJobClient;
private readonly ILogger _log; private readonly ILogger _log;
private readonly IHubContext<NotificationHub> _notification; private readonly IHubContext<NotificationHub> _notification;
@ -139,7 +135,8 @@ namespace Ombi.Schedule.Jobs.Plex
// We have ful-fulled this request! // We have ful-fulled this request!
child.Available = true; child.Available = true;
child.MarkedAsAvailable = DateTime.Now; child.MarkedAsAvailable = DateTime.Now;
await _notificationService.Publish(new NotificationOptions
await _notificationService.Notify(new NotificationOptions
{ {
DateTime = DateTime.Now, DateTime = DateTime.Now,
NotificationType = NotificationType.RequestAvailable, NotificationType = NotificationType.RequestAvailable,
@ -183,7 +180,7 @@ namespace Ombi.Schedule.Jobs.Plex
item.RequestId = movie.Id; item.RequestId = movie.Id;
_log.LogInformation("[PAC] - Movie request {0} is now available, sending notification", $"{movie.Title} - {movie.Id}"); _log.LogInformation("[PAC] - Movie request {0} is now available, sending notification", $"{movie.Title} - {movie.Id}");
await _notificationService.Publish(new NotificationOptions await _notificationService.Notify(new NotificationOptions
{ {
DateTime = DateTime.Now, DateTime = DateTime.Now,
NotificationType = NotificationType.RequestAvailable, NotificationType = NotificationType.RequestAvailable,
@ -206,8 +203,6 @@ namespace Ombi.Schedule.Jobs.Plex
if (disposing) if (disposing)
{ {
_movieRepo?.Dispose();
_repo?.Dispose();
} }
_disposed = true; _disposed = true;
} }

@ -29,7 +29,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Hangfire;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -120,9 +119,6 @@ namespace Ombi.Schedule.Jobs.Plex
{ {
Logger.LogInformation("Kicking off Plex Availability Checker"); Logger.LogInformation("Kicking off Plex Availability Checker");
await OmbiQuartz.TriggerJob(nameof(IPlexAvailabilityChecker), "Plex"); await OmbiQuartz.TriggerJob(nameof(IPlexAvailabilityChecker), "Plex");
Logger.LogInformation("Starting Metadata refresh");
// Just check what we send it
await OmbiQuartz.TriggerJob(nameof(IRefreshMetadata), "System");
} }
if ((processedContent?.HasProcessedContent ?? false) && recentlyAddedSearch) if ((processedContent?.HasProcessedContent ?? false) && recentlyAddedSearch)
@ -669,7 +665,6 @@ namespace Ombi.Schedule.Jobs.Plex
if (disposing) if (disposing)
{ {
Plex?.Dispose(); Plex?.Dispose();
Repo?.Dispose();
EpisodeSync?.Dispose(); EpisodeSync?.Dispose();
} }
_disposed = true; _disposed = true;

@ -2,7 +2,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Hangfire;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -12,6 +11,7 @@ using Ombi.Core.Settings;
using Ombi.Core.Settings.Models.External; using Ombi.Core.Settings.Models.External;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Hubs; using Ombi.Hubs;
using Ombi.Schedule.Jobs.Ombi;
using Ombi.Schedule.Jobs.Plex.Interfaces; using Ombi.Schedule.Jobs.Plex.Interfaces;
using Ombi.Store.Entities; using Ombi.Store.Entities;
using Ombi.Store.Repository; using Ombi.Store.Repository;
@ -63,7 +63,7 @@ namespace Ombi.Schedule.Jobs.Plex
_log.LogError(LoggingEvents.Cacher, e, "Caching Episodes Failed"); _log.LogError(LoggingEvents.Cacher, e, "Caching Episodes Failed");
} }
//await OmbiQuartz.TriggerJob(nameof(IRefreshMetadata), "System");
await OmbiQuartz.TriggerJob(nameof(IPlexAvailabilityChecker), "Plex"); await OmbiQuartz.TriggerJob(nameof(IPlexAvailabilityChecker), "Plex");
await _notification.Clients.Clients(NotificationHub.AdminConnectionIds) await _notification.Clients.Clients(NotificationHub.AdminConnectionIds)
.SendAsync(NotificationHub.NotificationEvent, "Plex Episode Sync Finished"); .SendAsync(NotificationHub.NotificationEvent, "Plex Episode Sync Finished");
@ -216,7 +216,6 @@ namespace Ombi.Schedule.Jobs.Plex
if (disposing) if (disposing)
{ {
_repo?.Dispose();
_settings?.Dispose(); _settings?.Dispose();
} }
_disposed = true; _disposed = true;

@ -10,13 +10,6 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Dapper" Version="1.50.2" /> <PackageReference Include="Dapper" Version="1.50.2" />
<PackageReference Include="Hangfire" Version="1.7.1" />
<PackageReference Include="Hangfire.AspNetCore" Version="1.7.1" />
<PackageReference Include="Hangfire.Console" Version="1.3.10" />
<PackageReference Include="Hangfire.MemoryStorage.Core" Version="1.4.0" />
<PackageReference Include="Hangfire.RecurringJobExtensions" Version="1.1.6" />
<PackageReference Include="Hangfire.SQLite" Version="1.4.2" />
<PackageReference Include="Microsoft.AspNet.SignalR" Version="2.4.1" />
<PackageReference Include="Quartz" Version="3.0.7" /> <PackageReference Include="Quartz" Version="3.0.7" />
<PackageReference Include="Serilog" Version="2.8.0" /> <PackageReference Include="Serilog" Version="2.8.0" />
<PackageReference Include="SharpCompress" Version="0.24.0" /> <PackageReference Include="SharpCompress" Version="0.24.0" />

@ -2,7 +2,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Ombi.Core.Notifications;
using Ombi.Core.Settings; using Ombi.Core.Settings;
using Ombi.Helpers;
using Ombi.Schedule.Jobs; using Ombi.Schedule.Jobs;
using Ombi.Schedule.Jobs.Couchpotato; using Ombi.Schedule.Jobs.Couchpotato;
using Ombi.Schedule.Jobs.Emby; using Ombi.Schedule.Jobs.Emby;
@ -53,6 +55,7 @@ namespace Ombi.Schedule
await AddEmby(s); await AddEmby(s);
await AddDvrApps(s); await AddDvrApps(s);
await AddSystem(s); await AddSystem(s);
await AddNotifications(s);
// Run Quartz // Run Quartz
await OmbiQuartz.Start(); await OmbiQuartz.Start();
@ -95,5 +98,9 @@ namespace Ombi.Schedule
await OmbiQuartz.Instance.AddJob<IEmbyAvaliabilityChecker>(nameof(IEmbyAvaliabilityChecker), "Emby", null); await OmbiQuartz.Instance.AddJob<IEmbyAvaliabilityChecker>(nameof(IEmbyAvaliabilityChecker), "Emby", null);
await OmbiQuartz.Instance.AddJob<IEmbyUserImporter>(nameof(IEmbyUserImporter), "Emby", JobSettingsHelper.UserImporter(s)); await OmbiQuartz.Instance.AddJob<IEmbyUserImporter>(nameof(IEmbyUserImporter), "Emby", JobSettingsHelper.UserImporter(s));
} }
private static async Task AddNotifications(JobSettings s)
{
await OmbiQuartz.Instance.AddJob<INotificationService>(nameof(INotificationService), "Notifications", null);
}
} }
} }

@ -0,0 +1,27 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Quartz;
namespace Ombi.Schedule
{
public class QuartzJobRunner : IJob
{
private readonly IServiceProvider _serviceProvider;
public QuartzJobRunner(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public async Task Execute(IJobExecutionContext context)
{
using (var scope = _serviceProvider.CreateScope())
{
var jobType = context.JobDetail.JobType;
var job = scope.ServiceProvider.GetRequiredService(jobType) as IJob;
await job.Execute(context);
}
}
}
}

@ -12,5 +12,10 @@ namespace Ombi.Store.Context.MySql
Database.Migrate(); Database.Migrate();
} }
public override void Dispose()
{
base.Dispose();
}
} }
} }

@ -1,4 +1,5 @@
using System; using System;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace Ombi.Store.Context.Sqlite namespace Ombi.Store.Context.Sqlite
@ -13,7 +14,9 @@ namespace Ombi.Store.Context.Sqlite
_created = true; _created = true;
Upgrade(); Upgrade();
Database.SetCommandTimeout(60); Database.SetCommandTimeout(60);
Database.Migrate(); Database.Migrate();
} }

@ -1,3 +1,3 @@
dotnet ef migrations add Inital --context OmbiContext --startup-project ../Ombi/Ombi.csproj dotnet ef migrations add Inital --context OmbiSqliteContext --startup-project ../Ombi/Ombi.csproj
If running migrations for any db provider other than Sqlite, then ensure the database.json is pointing at the correct DB type If running migrations for any db provider other than Sqlite, then ensure the database.json is pointing at the correct DB type

@ -0,0 +1,314 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Ombi.Store.Context.Sqlite;
namespace Ombi.Store.Migrations.ExternalSqlite
{
[DbContext(typeof(ExternalSqliteContext))]
[Migration("20191113213617_RequestIdPatch")]
partial class RequestIdPatch
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.2.6-servicing-10079");
modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("TheMovieDbId");
b.HasKey("Id");
b.ToTable("CouchPotatoCache");
});
modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime>("AddedAt");
b.Property<string>("EmbyId")
.IsRequired();
b.Property<string>("ImdbId");
b.Property<string>("ProviderId");
b.Property<string>("TheMovieDbId");
b.Property<string>("Title");
b.Property<string>("TvDbId");
b.Property<int>("Type");
b.Property<string>("Url");
b.HasKey("Id");
b.ToTable("EmbyContent");
});
modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime>("AddedAt");
b.Property<string>("EmbyId");
b.Property<int>("EpisodeNumber");
b.Property<string>("ImdbId");
b.Property<string>("ParentId");
b.Property<string>("ProviderId");
b.Property<int>("SeasonNumber");
b.Property<string>("TheMovieDbId");
b.Property<string>("Title");
b.Property<string>("TvDbId");
b.HasKey("Id");
b.HasIndex("ParentId");
b.ToTable("EmbyEpisode");
});
modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime>("AddedAt");
b.Property<int>("ArtistId");
b.Property<string>("ForeignAlbumId");
b.Property<bool>("Monitored");
b.Property<decimal>("PercentOfTracks");
b.Property<DateTime>("ReleaseDate");
b.Property<string>("Title");
b.Property<int>("TrackCount");
b.HasKey("Id");
b.ToTable("LidarrAlbumCache");
});
modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("ArtistId");
b.Property<string>("ArtistName");
b.Property<string>("ForeignArtistId");
b.Property<bool>("Monitored");
b.HasKey("Id");
b.ToTable("LidarrArtistCache");
});
modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("EpisodeNumber");
b.Property<int>("GrandparentKey");
b.Property<int>("Key");
b.Property<int>("ParentKey");
b.Property<int>("SeasonNumber");
b.Property<string>("Title");
b.HasKey("Id");
b.HasIndex("GrandparentKey");
b.ToTable("PlexEpisode");
});
modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("ParentKey");
b.Property<int>("PlexContentId");
b.Property<int?>("PlexServerContentId");
b.Property<int>("SeasonKey");
b.Property<int>("SeasonNumber");
b.HasKey("Id");
b.HasIndex("PlexServerContentId");
b.ToTable("PlexSeasonsContent");
});
modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<DateTime>("AddedAt");
b.Property<string>("ImdbId");
b.Property<int>("Key");
b.Property<string>("Quality");
b.Property<string>("ReleaseYear");
b.Property<int?>("RequestId");
b.Property<string>("TheMovieDbId");
b.Property<string>("Title");
b.Property<string>("TvDbId");
b.Property<int>("Type");
b.Property<string>("Url");
b.HasKey("Id");
b.ToTable("PlexServerContent");
});
modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<bool>("HasFile");
b.Property<int>("TheMovieDbId");
b.HasKey("Id");
b.ToTable("RadarrCache");
});
modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("TvDbId");
b.HasKey("Id");
b.ToTable("SickRageCache");
});
modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("EpisodeNumber");
b.Property<int>("SeasonNumber");
b.Property<int>("TvDbId");
b.HasKey("Id");
b.ToTable("SickRageEpisodeCache");
});
modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("TvDbId");
b.HasKey("Id");
b.ToTable("SonarrCache");
});
modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("EpisodeNumber");
b.Property<bool>("HasFile");
b.Property<int>("SeasonNumber");
b.Property<int>("TvDbId");
b.HasKey("Id");
b.ToTable("SonarrEpisodeCache");
});
modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b =>
{
b.HasOne("Ombi.Store.Entities.EmbyContent", "Series")
.WithMany("Episodes")
.HasForeignKey("ParentId")
.HasPrincipalKey("EmbyId");
});
modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b =>
{
b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series")
.WithMany("Episodes")
.HasForeignKey("GrandparentKey")
.HasPrincipalKey("Key")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b =>
{
b.HasOne("Ombi.Store.Entities.PlexServerContent")
.WithMany("Seasons")
.HasForeignKey("PlexServerContentId");
});
#pragma warning restore 612, 618
}
}
}

@ -0,0 +1,22 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Ombi.Store.Migrations.ExternalSqlite
{
public partial class RequestIdPatch : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
//migrationBuilder.AddColumn<int>(
// name: "RequestId",
// table: "PlexServerContent",
// nullable: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}

@ -107,25 +107,25 @@ namespace Ombi.Store.Repository
} }
private bool _disposed; //private bool _disposed;
// Protected implementation of Dispose pattern. //// Protected implementation of Dispose pattern.
protected virtual void Dispose(bool disposing) //protected virtual void Dispose(bool disposing)
{ //{
if (_disposed) // if (_disposed)
return; // return;
if (disposing) // if (disposing)
{ // {
_ctx?.Dispose(); // _ctx?.Dispose();
} // }
_disposed = true; // _disposed = true;
} //}
public void Dispose() //public void Dispose()
{ //{
Dispose(true); // Dispose(true);
GC.SuppressFinalize(this); // GC.SuppressFinalize(this);
} //}
} }
} }

@ -9,7 +9,7 @@ using Ombi.Store.Entities;
namespace Ombi.Store.Repository namespace Ombi.Store.Repository
{ {
public interface IExternalRepository<T> : IDisposable where T : Entity public interface IExternalRepository<T> where T : Entity
{ {
Task<T> Find(object key); Task<T> Find(object key);
IQueryable<T> GetAll(); IQueryable<T> GetAll();

@ -9,7 +9,7 @@ using Ombi.Store.Entities;
namespace Ombi.Store.Repository namespace Ombi.Store.Repository
{ {
public interface IRepository<T> : IDisposable where T : Entity public interface IRepository<T> where T : Entity
{ {
Task<T> Find(object key); Task<T> Find(object key);
IQueryable<T> GetAll(); IQueryable<T> GetAll();

@ -806,7 +806,8 @@
"@types/selenium-webdriver": { "@types/selenium-webdriver": {
"version": "3.0.16", "version": "3.0.16",
"resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.16.tgz", "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.16.tgz",
"integrity": "sha512-lMC2G0ItF2xv4UCiwbJGbnJlIuUixHrioOhNGHSCsYCJ8l4t9hMCUimCytvFv7qy6AfSzRxhRHoGa+UqaqwyeA==" "integrity": "sha512-lMC2G0ItF2xv4UCiwbJGbnJlIuUixHrioOhNGHSCsYCJ8l4t9hMCUimCytvFv7qy6AfSzRxhRHoGa+UqaqwyeA==",
"optional": true
}, },
"@types/sizzle": { "@types/sizzle": {
"version": "2.3.2", "version": "2.3.2",
@ -1247,6 +1248,7 @@
"version": "1.1.5", "version": "1.1.5",
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
"integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
"optional": true,
"requires": { "requires": {
"delegates": "^1.0.0", "delegates": "^1.0.0",
"readable-stream": "^2.0.6" "readable-stream": "^2.0.6"
@ -2429,7 +2431,8 @@
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
"optional": true
}, },
"constants-browserify": { "constants-browserify": {
"version": "1.0.0", "version": "1.0.0",
@ -2489,6 +2492,11 @@
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=",
"dev": true "dev": true
}, },
"cookiejar": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz",
"integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA=="
},
"copy-concurrently": { "copy-concurrently": {
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz",
@ -2834,7 +2842,8 @@
"delegates": { "delegates": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
"optional": true
}, },
"depd": { "depd": {
"version": "1.1.2", "version": "1.1.2",
@ -3614,6 +3623,7 @@
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
"integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
"optional": true,
"requires": { "requires": {
"path-exists": "^2.0.0", "path-exists": "^2.0.0",
"pinkie-promise": "^2.0.0" "pinkie-promise": "^2.0.0"
@ -3689,6 +3699,11 @@
"mime-types": "^2.1.12" "mime-types": "^2.1.12"
} }
}, },
"formidable": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz",
"integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg=="
},
"forwarded": { "forwarded": {
"version": "0.1.2", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
@ -3765,7 +3780,8 @@
"ansi-regex": { "ansi-regex": {
"version": "2.1.1", "version": "2.1.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"aproba": { "aproba": {
"version": "1.2.0", "version": "1.2.0",
@ -3786,12 +3802,14 @@
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"brace-expansion": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
"concat-map": "0.0.1" "concat-map": "0.0.1"
@ -3806,17 +3824,20 @@
"code-point-at": { "code-point-at": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"core-util-is": { "core-util-is": {
"version": "1.0.2", "version": "1.0.2",
@ -3933,7 +3954,8 @@
"inherits": { "inherits": {
"version": "2.0.3", "version": "2.0.3",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.5",
@ -3945,6 +3967,7 @@
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"number-is-nan": "^1.0.0" "number-is-nan": "^1.0.0"
} }
@ -3959,6 +3982,7 @@
"version": "3.0.4", "version": "3.0.4",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
} }
@ -3966,12 +3990,14 @@
"minimist": { "minimist": {
"version": "0.0.8", "version": "0.0.8",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"minipass": { "minipass": {
"version": "2.3.5", "version": "2.3.5",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"safe-buffer": "^5.1.2", "safe-buffer": "^5.1.2",
"yallist": "^3.0.0" "yallist": "^3.0.0"
@ -3990,6 +4016,7 @@
"version": "0.5.1", "version": "0.5.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"minimist": "0.0.8" "minimist": "0.0.8"
} }
@ -4070,7 +4097,8 @@
"number-is-nan": { "number-is-nan": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"object-assign": { "object-assign": {
"version": "4.1.1", "version": "4.1.1",
@ -4082,6 +4110,7 @@
"version": "1.4.0", "version": "1.4.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"wrappy": "1" "wrappy": "1"
} }
@ -4167,7 +4196,8 @@
"safe-buffer": { "safe-buffer": {
"version": "5.1.2", "version": "5.1.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"safer-buffer": { "safer-buffer": {
"version": "2.1.2", "version": "2.1.2",
@ -4203,6 +4233,7 @@
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"code-point-at": "^1.0.0", "code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0", "is-fullwidth-code-point": "^1.0.0",
@ -4222,6 +4253,7 @@
"version": "3.0.1", "version": "3.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"ansi-regex": "^2.0.0" "ansi-regex": "^2.0.0"
} }
@ -4265,12 +4297,14 @@
"wrappy": { "wrappy": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"yallist": { "yallist": {
"version": "3.0.3", "version": "3.0.3",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
} }
} }
}, },
@ -4278,6 +4312,7 @@
"version": "1.0.12", "version": "1.0.12",
"resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
"integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
"optional": true,
"requires": { "requires": {
"graceful-fs": "^4.1.2", "graceful-fs": "^4.1.2",
"inherits": "~2.0.0", "inherits": "~2.0.0",
@ -4285,6 +4320,18 @@
"rimraf": "2" "rimraf": "2"
} }
}, },
"fullcalendar": {
"version": "4.0.0-alpha.4",
"resolved": "https://registry.npmjs.org/fullcalendar/-/fullcalendar-4.0.0-alpha.4.tgz",
"integrity": "sha512-6uup/KTSSlybpj3ntiYvDlpbU82Z9deeW9D8zO/MJLcsKD/i+I4kWEnoJLp1egZdAHq9xGsJ9PLTBU/xz6QqGw==",
"requires": {
"luxon": "^1.10.0",
"moment": "^2.23.0",
"moment-timezone": "^0.5.23",
"rrule": "^2.6.0",
"superagent": "^3.8.3"
}
},
"function-bind": { "function-bind": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
@ -4294,6 +4341,7 @@
"version": "2.7.4", "version": "2.7.4",
"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
"integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
"optional": true,
"requires": { "requires": {
"aproba": "^1.0.3", "aproba": "^1.0.3",
"console-control-strings": "^1.0.0", "console-control-strings": "^1.0.0",
@ -4328,7 +4376,8 @@
"get-stdin": { "get-stdin": {
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
"integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
"optional": true
}, },
"get-stream": { "get-stream": {
"version": "4.1.0", "version": "4.1.0",
@ -4488,7 +4537,8 @@
"has-unicode": { "has-unicode": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
"optional": true
}, },
"has-value": { "has-value": {
"version": "1.0.0", "version": "1.0.0",
@ -4750,7 +4800,8 @@
"immediate": { "immediate": {
"version": "3.0.6", "version": "3.0.6",
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
"integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=",
"optional": true
}, },
"import-cwd": { "import-cwd": {
"version": "2.1.0", "version": "2.1.0",
@ -5151,7 +5202,8 @@
"is-utf8": { "is-utf8": {
"version": "0.2.1", "version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
"integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
"optional": true
}, },
"is-windows": { "is-windows": {
"version": "1.0.2", "version": "1.0.2",
@ -5375,6 +5427,7 @@
"version": "3.2.2", "version": "3.2.2",
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.2.2.tgz", "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.2.2.tgz",
"integrity": "sha512-NmKajvAFQpbg3taXQXr/ccS2wcucR1AZ+NtyWp2Nq7HHVsXhcJFR8p0Baf32C2yVvBylFWVeKf+WI2AnvlPhpA==", "integrity": "sha512-NmKajvAFQpbg3taXQXr/ccS2wcucR1AZ+NtyWp2Nq7HHVsXhcJFR8p0Baf32C2yVvBylFWVeKf+WI2AnvlPhpA==",
"optional": true,
"requires": { "requires": {
"lie": "~3.3.0", "lie": "~3.3.0",
"pako": "~1.0.2", "pako": "~1.0.2",
@ -5470,6 +5523,7 @@
"version": "3.3.0", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
"integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
"optional": true,
"requires": { "requires": {
"immediate": "~3.0.5" "immediate": "~3.0.5"
} }
@ -5478,6 +5532,7 @@
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
"integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
"optional": true,
"requires": { "requires": {
"graceful-fs": "^4.1.2", "graceful-fs": "^4.1.2",
"parse-json": "^2.2.0", "parse-json": "^2.2.0",
@ -5589,6 +5644,11 @@
"yallist": "^2.1.2" "yallist": "^2.1.2"
} }
}, },
"luxon": {
"version": "1.21.2",
"resolved": "https://registry.npmjs.org/luxon/-/luxon-1.21.2.tgz",
"integrity": "sha512-yshwnlkA79WfC24/BC9Rd1n0mhorP22Sc7GYn0puRU6wD/douCgNJIzI9qQBuT9m2/bU+n9v1RflVNE4rMPPxQ=="
},
"magic-string": { "magic-string": {
"version": "0.25.2", "version": "0.25.2",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.2.tgz", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.2.tgz",
@ -5681,7 +5741,8 @@
"map-obj": { "map-obj": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
"integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=",
"optional": true
}, },
"map-visit": { "map-visit": {
"version": "1.0.0", "version": "1.0.0",
@ -5755,8 +5816,7 @@
"methods": { "methods": {
"version": "1.1.2", "version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
"dev": true
}, },
"micromatch": { "micromatch": {
"version": "3.1.10", "version": "3.1.10",
@ -5791,8 +5851,7 @@
"mime": { "mime": {
"version": "1.6.0", "version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
"dev": true
}, },
"mime-db": { "mime-db": {
"version": "1.40.0", "version": "1.40.0",
@ -5952,6 +6011,14 @@
"resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
"integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
}, },
"moment-timezone": {
"version": "0.5.27",
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.27.tgz",
"integrity": "sha512-EIKQs7h5sAsjhPCqN6ggx6cEbs94GK050254TIJySD1bzoM5JTYDwAU1IoVOeTOL6Gm27kYJ51/uuvq1kIlrbw==",
"requires": {
"moment": ">= 2.9.0"
}
},
"move-concurrently": { "move-concurrently": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
@ -6376,6 +6443,7 @@
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
"integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
"optional": true,
"requires": { "requires": {
"are-we-there-yet": "~1.1.2", "are-we-there-yet": "~1.1.2",
"console-control-strings": "~1.1.0", "console-control-strings": "~1.1.0",
@ -6751,6 +6819,7 @@
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
"integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
"optional": true,
"requires": { "requires": {
"error-ex": "^1.2.0" "error-ex": "^1.2.0"
} }
@ -6804,6 +6873,7 @@
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
"integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
"optional": true,
"requires": { "requires": {
"pinkie-promise": "^2.0.0" "pinkie-promise": "^2.0.0"
} }
@ -6839,6 +6909,7 @@
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
"integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
"optional": true,
"requires": { "requires": {
"graceful-fs": "^4.1.2", "graceful-fs": "^4.1.2",
"pify": "^2.0.0", "pify": "^2.0.0",
@ -7091,12 +7162,14 @@
"ansi-styles": { "ansi-styles": {
"version": "2.2.1", "version": "2.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
"optional": true
}, },
"chalk": { "chalk": {
"version": "1.1.3", "version": "1.1.3",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
"optional": true,
"requires": { "requires": {
"ansi-styles": "^2.2.1", "ansi-styles": "^2.2.1",
"escape-string-regexp": "^1.0.2", "escape-string-regexp": "^1.0.2",
@ -7117,7 +7190,8 @@
"supports-color": { "supports-color": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
"optional": true
}, },
"webdriver-manager": { "webdriver-manager": {
"version": "12.1.5", "version": "12.1.5",
@ -7221,7 +7295,8 @@
"q": { "q": {
"version": "1.4.1", "version": "1.4.1",
"resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz",
"integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=" "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=",
"optional": true
}, },
"qs": { "qs": {
"version": "6.5.2", "version": "6.5.2",
@ -7349,6 +7424,7 @@
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
"integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
"optional": true,
"requires": { "requires": {
"load-json-file": "^1.0.0", "load-json-file": "^1.0.0",
"normalize-package-data": "^2.3.2", "normalize-package-data": "^2.3.2",
@ -7359,6 +7435,7 @@
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
"integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
"optional": true,
"requires": { "requires": {
"find-up": "^1.0.0", "find-up": "^1.0.0",
"read-pkg": "^1.0.0" "read-pkg": "^1.0.0"
@ -7609,6 +7686,15 @@
"inherits": "^2.0.1" "inherits": "^2.0.1"
} }
}, },
"rrule": {
"version": "2.6.3",
"resolved": "https://registry.npmjs.org/rrule/-/rrule-2.6.3.tgz",
"integrity": "sha512-wWypJiQekvgZLGNKSI8OvC8KtAvA/L/CtF1EjI9qmZEkT/6WIyRL5rdIy5FfeC4z33aRp90/0KuAdHmLdw0KgA==",
"requires": {
"luxon": "^1.3.3",
"tslib": "^1.9.0"
}
},
"run-async": { "run-async": {
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
@ -7708,7 +7794,8 @@
"sax": { "sax": {
"version": "1.2.4", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
"optional": true
}, },
"schema-utils": { "schema-utils": {
"version": "1.0.0", "version": "1.0.0",
@ -7752,6 +7839,7 @@
"version": "3.6.0", "version": "3.6.0",
"resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz", "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz",
"integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==", "integrity": "sha512-WH7Aldse+2P5bbFBO4Gle/nuQOdVwpHMTL6raL3uuBj/vPG07k6uzt3aiahu352ONBr5xXh0hDlM3LhtXPOC4Q==",
"optional": true,
"requires": { "requires": {
"jszip": "^3.1.3", "jszip": "^3.1.3",
"rimraf": "^2.5.4", "rimraf": "^2.5.4",
@ -7886,7 +7974,8 @@
"set-immediate-shim": { "set-immediate-shim": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
"integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=" "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=",
"optional": true
}, },
"set-value": { "set-value": {
"version": "2.0.1", "version": "2.0.1",
@ -8588,6 +8677,7 @@
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
"integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
"optional": true,
"requires": { "requires": {
"is-utf8": "^0.2.0" "is-utf8": "^0.2.0"
} }
@ -8673,6 +8763,38 @@
"when": "~3.6.x" "when": "~3.6.x"
} }
}, },
"superagent": {
"version": "3.8.3",
"resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.3.tgz",
"integrity": "sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA==",
"requires": {
"component-emitter": "^1.2.0",
"cookiejar": "^2.1.0",
"debug": "^3.1.0",
"extend": "^3.0.0",
"form-data": "^2.3.1",
"formidable": "^1.2.0",
"methods": "^1.1.1",
"mime": "^1.4.1",
"qs": "^6.5.1",
"readable-stream": "^2.3.5"
},
"dependencies": {
"debug": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
"requires": {
"ms": "^2.1.1"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
}
}
},
"supports-color": { "supports-color": {
"version": "5.5.0", "version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
@ -8785,6 +8907,7 @@
"version": "0.0.30", "version": "0.0.30",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.30.tgz",
"integrity": "sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=", "integrity": "sha1-ckGdSovn1s51FI/YsyTlk6cRwu0=",
"optional": true,
"requires": { "requires": {
"os-tmpdir": "~1.0.1" "os-tmpdir": "~1.0.1"
} }
@ -9708,6 +9831,7 @@
"version": "1.1.3", "version": "1.1.3",
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
"integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
"optional": true,
"requires": { "requires": {
"string-width": "^1.0.2 || 2" "string-width": "^1.0.2 || 2"
} }
@ -9767,6 +9891,7 @@
"version": "0.4.19", "version": "0.4.19",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",
"integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==",
"optional": true,
"requires": { "requires": {
"sax": ">=0.6.0", "sax": ">=0.6.0",
"xmlbuilder": "~9.0.1" "xmlbuilder": "~9.0.1"
@ -9775,7 +9900,8 @@
"xmlbuilder": { "xmlbuilder": {
"version": "9.0.7", "version": "9.0.7",
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
"integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=",
"optional": true
}, },
"xmlhttprequest-ssl": { "xmlhttprequest-ssl": {
"version": "1.5.5", "version": "1.5.5",

@ -42,7 +42,7 @@
"core-js": "^2.5.4", "core-js": "^2.5.4",
"eventemitter2": "^5.0.1", "eventemitter2": "^5.0.1",
"font-awesome": "^4.7.0", "font-awesome": "^4.7.0",
"fullcalendar":"^4.0.0-alpha.4", "fullcalendar": "^4.0.0-alpha.4",
"hammerjs": "^2.0.8", "hammerjs": "^2.0.8",
"jquery": "3.3.1", "jquery": "3.3.1",
"moment": "^2.23.0", "moment": "^2.23.0",

@ -164,7 +164,7 @@ export class LoginComponent implements OnDestroy, OnInit {
duration: 3000 duration: 3000
}); });
this.getPinResult(x.pinId); this.getPinResult(x.pinId);
}, 10000); }, 4000);
}); });
}); });
} }

@ -1,4 +1,3 @@
@import "./Styles.scss"; @import "./shared.scss";
@import "./shared.scss";
@import "./buttons.scss"; @import "./buttons.scss";
@import "./primeng-overrides.scss" @import "./primeng-overrides.scss"

@ -30,7 +30,7 @@ $warn: mat-color($ombi-app-warn);
// DARK // DARK
$background-dark: at-color(mat-palette($mat-grey, 800));; $background-dark: mat-color(mat-palette($mat-grey, 800));;
$backgroundTint-dark: mat-color(mat-palette($mat-grey, 900)); $backgroundTint-dark: mat-color(mat-palette($mat-grey, 900));
$text-dark: white; $text-dark: white;
$panel: mat-color(mat-palette($mat-grey, 800)); $panel: mat-color(mat-palette($mat-grey, 800));

@ -4,7 +4,6 @@ using System.Linq;
using System.Net; using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
using AutoMapper; using AutoMapper;
using Hangfire;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
@ -860,7 +859,7 @@ namespace Ombi.Controllers.V1
[HttpPost("welcomeEmail")] [HttpPost("welcomeEmail")]
[PowerUser] [PowerUser]
public void SendWelcomeEmail([FromBody] UserViewModel user) public async Task<IActionResult> SendWelcomeEmail([FromBody] UserViewModel user)
{ {
var ombiUser = new OmbiUser var ombiUser = new OmbiUser
{ {
@ -868,7 +867,8 @@ namespace Ombi.Controllers.V1
Email = user.EmailAddress, Email = user.EmailAddress,
UserName = user.UserName UserName = user.UserName
}; };
BackgroundJob.Enqueue(() => WelcomeEmail.SendEmail(ombiUser)); await WelcomeEmail.SendEmail(ombiUser);
return Ok();
} }
[HttpGet("accesstoken")] [HttpGet("accesstoken")]

@ -2,12 +2,12 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Hangfire;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Ombi.Attributes; using Ombi.Attributes;
using Ombi.Core;
using Ombi.Core.Notifications; using Ombi.Core.Notifications;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Models; using Ombi.Models;
@ -25,7 +25,7 @@ namespace Ombi.Controllers.V1
public class IssuesController : ControllerBase public class IssuesController : ControllerBase
{ {
public IssuesController(IRepository<IssueCategory> categories, IRepository<Issues> issues, IRepository<IssueComments> comments, public IssuesController(IRepository<IssueCategory> categories, IRepository<Issues> issues, IRepository<IssueComments> comments,
UserManager<OmbiUser> userManager, INotificationService notify) UserManager<OmbiUser> userManager, INotificationHelper notify)
{ {
_categories = categories; _categories = categories;
_issues = issues; _issues = issues;
@ -38,7 +38,7 @@ namespace Ombi.Controllers.V1
private readonly IRepository<Issues> _issues; private readonly IRepository<Issues> _issues;
private readonly IRepository<IssueComments> _issueComments; private readonly IRepository<IssueComments> _issueComments;
private readonly UserManager<OmbiUser> _userManager; private readonly UserManager<OmbiUser> _userManager;
private readonly INotificationService _notification; private readonly INotificationHelper _notification;
/// <summary> /// <summary>
/// Get's all categories /// Get's all categories
@ -150,7 +150,7 @@ namespace Ombi.Controllers.V1
AddIssueNotificationSubstitutes(notificationModel, i, User.Identity.Name); AddIssueNotificationSubstitutes(notificationModel, i, User.Identity.Name);
BackgroundJob.Enqueue(() => _notification.Publish(notificationModel)); await _notification.Notify(notificationModel);
return i.Id; return i.Id;
} }
@ -237,7 +237,7 @@ namespace Ombi.Controllers.V1
notificationModel.Recipient = user.Email; notificationModel.Recipient = user.Email;
} }
BackgroundJob.Enqueue(() => _notification.Publish(notificationModel)); await _notification.Notify(notificationModel);
return await _issueComments.Add(newComment); return await _issueComments.Add(newComment);
} }
@ -290,7 +290,7 @@ namespace Ombi.Controllers.V1
}; };
AddIssueNotificationSubstitutes(notificationModel, issue, issue.UserReported?.UserAlias ?? string.Empty); AddIssueNotificationSubstitutes(notificationModel, issue, issue.UserReported?.UserAlias ?? string.Empty);
BackgroundJob.Enqueue(() => _notification.Publish(notificationModel)); await _notification.Notify(notificationModel);
} }

@ -1,11 +1,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Hangfire;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Ombi.Attributes; using Ombi.Attributes;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Schedule;
using Ombi.Schedule.Jobs; using Ombi.Schedule.Jobs;
using Ombi.Schedule.Jobs.Emby; using Ombi.Schedule.Jobs.Emby;
using Ombi.Schedule.Jobs.Ombi; using Ombi.Schedule.Jobs.Ombi;

@ -7,10 +7,8 @@ using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading.Tasks; using System.Threading.Tasks;
using AutoMapper; using AutoMapper;
using Hangfire;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using NCrontab;
using Ombi.Api.Emby; using Ombi.Api.Emby;
using Ombi.Api.Github; using Ombi.Api.Github;
using Ombi.Attributes; using Ombi.Attributes;
@ -30,7 +28,6 @@ using Ombi.Store.Repository;
using Ombi.Api.Github; using Ombi.Api.Github;
using Ombi.Core.Engine; using Ombi.Core.Engine;
using Ombi.Extensions; using Ombi.Extensions;
using Ombi.Schedule;
using Quartz; using Quartz;
namespace Ombi.Controllers.V1 namespace Ombi.Controllers.V1

@ -58,8 +58,6 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="AutoMapper" Version="6.1.1" /> <PackageReference Include="AutoMapper" Version="6.1.1" />
<PackageReference Include="CommandLineParser" Version="2.6.0" /> <PackageReference Include="CommandLineParser" Version="2.6.0" />
<PackageReference Include="Hangfire.AspNetCore" Version="1.7.1" />
<PackageReference Include="Hangfire.SQLite" Version="1.4.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="3.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.0.0" />

@ -1,8 +1,5 @@
using AutoMapper; using AutoMapper;
using AutoMapper.EquivalencyExpression; using AutoMapper.EquivalencyExpression;
using Hangfire;
using Hangfire.Dashboard;
using Hangfire.MemoryStorage;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
@ -94,15 +91,6 @@ namespace Ombi
services.AddSwagger(); services.AddSwagger();
services.AddAppSettingsValues(Configuration); services.AddAppSettingsValues(Configuration);
services.AddHangfire(x =>
{
x.UseMemoryStorage();
#pragma warning disable ASP0000 // Do not call 'IServiceCollection.BuildServiceProvider' in 'ConfigureServices'
x.UseActivator(new IoCJobActivator(services.BuildServiceProvider()));
#pragma warning restore ASP0000 // Do not call 'IServiceCollection.BuildServiceProvider' in 'ConfigureServices'
});
services.AddCors(o => o.AddPolicy("MyPolicy", builder => services.AddCors(o => o.AddPolicy("MyPolicy", builder =>
{ {
builder.AllowAnyHeader() builder.AllowAnyHeader()
@ -171,9 +159,9 @@ namespace Ombi
app.UsePathBase(settings.BaseUrl); app.UsePathBase(settings.BaseUrl);
} }
app.UseHangfireServer(new BackgroundJobServerOptions // Setup the scheduler
{WorkerCount = 1, ServerTimeout = TimeSpan.FromDays(1), ShutdownTimeout = TimeSpan.FromDays(1)}); //var jobSetup = app.ApplicationServices.GetService<IJobSetup>();
//jobSetup.Setup();
ctx.Seed(); ctx.Seed();
var settingsctx = serviceProvider.GetService<SettingsContext>(); var settingsctx = serviceProvider.GetService<SettingsContext>();
settingsctx.Seed(); settingsctx.Seed();

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save