Added the availablility checker #2313 !wip

pull/2478/head
Jamie 6 years ago
parent 5df232f3f5
commit 82d610e235

@ -20,8 +20,8 @@ namespace Ombi.Notifications.Agents
{ {
public DiscordNotification(IDiscordApi api, ISettingsService<DiscordNotificationSettings> sn, public DiscordNotification(IDiscordApi api, ISettingsService<DiscordNotificationSettings> sn,
ILogger<DiscordNotification> log, INotificationTemplatesRepository r, ILogger<DiscordNotification> log, INotificationTemplatesRepository r,
IMovieRequestRepository m, ITvRequestRepository t, ISettingsService<CustomizationSettings> s, IRepository<RequestSubscription> sub) IMovieRequestRepository m, ITvRequestRepository t, ISettingsService<CustomizationSettings> s, IRepository<RequestSubscription> sub, IMusicRequestRepository music)
: base(sn, r, m, t,s,log, sub) : base(sn, r, m, t, s, log, sub, music)
{ {
Api = api; Api = api;
Logger = log; Logger = log;
@ -130,12 +130,18 @@ namespace Ombi.Notifications.Agents
title = MovieRequest.Title; title = MovieRequest.Title;
image = MovieRequest.PosterPath; image = MovieRequest.PosterPath;
} }
else else if (model.RequestType == RequestType.TvShow)
{ {
user = TvRequest.RequestedUser.UserAlias; user = TvRequest.RequestedUser.UserAlias;
title = TvRequest.ParentRequest.Title; title = TvRequest.ParentRequest.Title;
image = TvRequest.ParentRequest.PosterPath; image = TvRequest.ParentRequest.PosterPath;
} }
else if (model.RequestType == RequestType.Album)
{
user = AlbumRequest.RequestedUser.UserAlias;
title = AlbumRequest.Title;
image = AlbumRequest.Cover;
}
var message = $"Hello! The user '{user}' has requested {title} but it could not be added. This has been added into the requests queue and will keep retrying"; var message = $"Hello! The user '{user}' has requested {title} but it could not be added. This has been added into the requests queue and will keep retrying";
var notification = new NotificationMessage var notification = new NotificationMessage
{ {

@ -22,7 +22,7 @@ namespace Ombi.Notifications.Agents
public class EmailNotification : BaseNotification<EmailNotificationSettings>, IEmailNotification public class EmailNotification : BaseNotification<EmailNotificationSettings>, IEmailNotification
{ {
public EmailNotification(ISettingsService<EmailNotificationSettings> settings, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, IEmailProvider prov, ISettingsService<CustomizationSettings> c, public EmailNotification(ISettingsService<EmailNotificationSettings> settings, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, IEmailProvider prov, ISettingsService<CustomizationSettings> c,
ILogger<EmailNotification> log, UserManager<OmbiUser> um, IRepository<RequestSubscription> sub) : base(settings, r, m, t, c, log, sub) ILogger<EmailNotification> log, UserManager<OmbiUser> um, IRepository<RequestSubscription> sub, IMusicRequestRepository music) : base(settings, r, m, t, c, log, sub, music)
{ {
EmailProvider = prov; EmailProvider = prov;
Logger = log; Logger = log;

@ -21,7 +21,7 @@ namespace Ombi.Notifications.Agents
public class MattermostNotification : BaseNotification<MattermostNotificationSettings>, IMattermostNotification public class MattermostNotification : BaseNotification<MattermostNotificationSettings>, IMattermostNotification
{ {
public MattermostNotification(IMattermostApi api, ISettingsService<MattermostNotificationSettings> sn, ILogger<MattermostNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, public MattermostNotification(IMattermostApi api, ISettingsService<MattermostNotificationSettings> sn, ILogger<MattermostNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
ISettingsService<CustomizationSettings> s, IRepository<RequestSubscription> sub) : base(sn, r, m, t,s,log, sub) ISettingsService<CustomizationSettings> s, IRepository<RequestSubscription> sub, IMusicRequestRepository music) : base(sn, r, m, t, s, log, sub, music)
{ {
Api = api; Api = api;
Logger = log; Logger = log;

@ -22,7 +22,7 @@ namespace Ombi.Notifications.Agents
{ {
public MobileNotification(IOneSignalApi api, ISettingsService<MobileNotificationSettings> sn, ILogger<MobileNotification> log, INotificationTemplatesRepository r, public MobileNotification(IOneSignalApi api, ISettingsService<MobileNotificationSettings> sn, ILogger<MobileNotification> log, INotificationTemplatesRepository r,
IMovieRequestRepository m, ITvRequestRepository t, ISettingsService<CustomizationSettings> s, IRepository<NotificationUserId> notification, IMovieRequestRepository m, ITvRequestRepository t, ISettingsService<CustomizationSettings> s, IRepository<NotificationUserId> notification,
UserManager<OmbiUser> um, IRepository<RequestSubscription> sub) : base(sn, r, m, t, s,log, sub) UserManager<OmbiUser> um, IRepository<RequestSubscription> sub, IMusicRequestRepository music) : base(sn, r, m, t, s, log, sub, music)
{ {
_api = api; _api = api;
_logger = log; _logger = log;

@ -17,7 +17,7 @@ namespace Ombi.Notifications.Agents
public class PushbulletNotification : BaseNotification<PushbulletSettings>, IPushbulletNotification public class PushbulletNotification : BaseNotification<PushbulletSettings>, IPushbulletNotification
{ {
public PushbulletNotification(IPushbulletApi api, ISettingsService<PushbulletSettings> sn, ILogger<PushbulletNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, public PushbulletNotification(IPushbulletApi api, ISettingsService<PushbulletSettings> sn, ILogger<PushbulletNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
ISettingsService<CustomizationSettings> s, IRepository<RequestSubscription> sub) : base(sn, r, m, t,s,log, sub) ISettingsService<CustomizationSettings> s, IRepository<RequestSubscription> sub, IMusicRequestRepository music) : base(sn, r, m, t, s, log, sub, music)
{ {
Api = api; Api = api;
Logger = log; Logger = log;

@ -18,7 +18,7 @@ namespace Ombi.Notifications.Agents
public class PushoverNotification : BaseNotification<PushoverSettings>, IPushoverNotification public class PushoverNotification : BaseNotification<PushoverSettings>, IPushoverNotification
{ {
public PushoverNotification(IPushoverApi api, ISettingsService<PushoverSettings> sn, ILogger<PushoverNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, public PushoverNotification(IPushoverApi api, ISettingsService<PushoverSettings> sn, ILogger<PushoverNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
ISettingsService<CustomizationSettings> s, IRepository<RequestSubscription> sub) : base(sn, r, m, t, s, log, sub) ISettingsService<CustomizationSettings> s, IRepository<RequestSubscription> sub, IMusicRequestRepository music) : base(sn, r, m, t, s, log, sub, music)
{ {
Api = api; Api = api;
Logger = log; Logger = log;

@ -18,7 +18,7 @@ namespace Ombi.Notifications.Agents
public class SlackNotification : BaseNotification<SlackNotificationSettings>, ISlackNotification public class SlackNotification : BaseNotification<SlackNotificationSettings>, ISlackNotification
{ {
public SlackNotification(ISlackApi api, ISettingsService<SlackNotificationSettings> sn, ILogger<SlackNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, public SlackNotification(ISlackApi api, ISettingsService<SlackNotificationSettings> sn, ILogger<SlackNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
ISettingsService<CustomizationSettings> s, IRepository<RequestSubscription> sub) : base(sn, r, m, t, s, log, sub) ISettingsService<CustomizationSettings> s, IRepository<RequestSubscription> sub, IMusicRequestRepository music) : base(sn, r, m, t, s, log, sub, music)
{ {
Api = api; Api = api;
Logger = log; Logger = log;

@ -19,7 +19,7 @@ namespace Ombi.Notifications.Agents
public TelegramNotification(ITelegramApi api, ISettingsService<TelegramSettings> sn, ILogger<TelegramNotification> log, public TelegramNotification(ITelegramApi api, ISettingsService<TelegramSettings> sn, ILogger<TelegramNotification> log,
INotificationTemplatesRepository r, IMovieRequestRepository m, INotificationTemplatesRepository r, IMovieRequestRepository m,
ITvRequestRepository t, ISettingsService<CustomizationSettings> s ITvRequestRepository t, ISettingsService<CustomizationSettings> s
, IRepository<RequestSubscription> sub) : base(sn, r, m, t,s,log, sub) , IRepository<RequestSubscription> sub, IMusicRequestRepository music) : base(sn, r, m, t,s,log, sub, music)
{ {
Api = api; Api = api;
Logger = log; Logger = log;

@ -19,7 +19,7 @@ namespace Ombi.Notifications.Interfaces
public abstract class BaseNotification<T> : INotification where T : Settings.Settings.Models.Settings, new() public abstract class BaseNotification<T> : INotification where T : Settings.Settings.Models.Settings, new()
{ {
protected BaseNotification(ISettingsService<T> settings, INotificationTemplatesRepository templateRepo, IMovieRequestRepository movie, ITvRequestRepository tv, protected BaseNotification(ISettingsService<T> settings, INotificationTemplatesRepository templateRepo, IMovieRequestRepository movie, ITvRequestRepository tv,
ISettingsService<CustomizationSettings> customization, ILogger<BaseNotification<T>> log, IRepository<RequestSubscription> sub) ISettingsService<CustomizationSettings> customization, ILogger<BaseNotification<T>> log, IRepository<RequestSubscription> sub, IMusicRequestRepository album)
{ {
Settings = settings; Settings = settings;
TemplateRepository = templateRepo; TemplateRepository = templateRepo;
@ -30,12 +30,14 @@ namespace Ombi.Notifications.Interfaces
CustomizationSettings.ClearCache(); CustomizationSettings.ClearCache();
RequestSubscription = sub; RequestSubscription = sub;
_log = log; _log = log;
AlbumRepository = album;
} }
protected ISettingsService<T> Settings { get; } protected ISettingsService<T> Settings { get; }
protected INotificationTemplatesRepository TemplateRepository { get; } protected INotificationTemplatesRepository TemplateRepository { get; }
protected IMovieRequestRepository MovieRepository { get; } protected IMovieRequestRepository MovieRepository { get; }
protected ITvRequestRepository TvRepository { get; } protected ITvRequestRepository TvRepository { get; }
protected IMusicRequestRepository AlbumRepository { get; }
protected CustomizationSettings Customization { get; set; } protected CustomizationSettings Customization { get; set; }
protected IRepository<RequestSubscription> RequestSubscription { get; set; } protected IRepository<RequestSubscription> RequestSubscription { get; set; }
private ISettingsService<CustomizationSettings> CustomizationSettings { get; } private ISettingsService<CustomizationSettings> CustomizationSettings { get; }
@ -43,6 +45,7 @@ namespace Ombi.Notifications.Interfaces
protected ChildRequests TvRequest { get; set; } protected ChildRequests TvRequest { get; set; }
protected AlbumRequest AlbumRequest { get; set; }
protected MovieRequests MovieRequest { get; set; } protected MovieRequests MovieRequest { get; set; }
protected IQueryable<OmbiUser> SubsribedUsers { get; private set; } protected IQueryable<OmbiUser> SubsribedUsers { get; private set; }
@ -130,10 +133,14 @@ namespace Ombi.Notifications.Interfaces
{ {
MovieRequest = await MovieRepository.GetWithUser().FirstOrDefaultAsync(x => x.Id == requestId); MovieRequest = await MovieRepository.GetWithUser().FirstOrDefaultAsync(x => x.Id == requestId);
} }
else else if (type == RequestType.TvShow)
{ {
TvRequest = await TvRepository.GetChild().FirstOrDefaultAsync(x => x.Id == requestId); TvRequest = await TvRepository.GetChild().FirstOrDefaultAsync(x => x.Id == requestId);
} }
else if (type == RequestType.Album)
{
AlbumRequest = await AlbumRepository.GetWithUser().FirstOrDefaultAsync(x => x.Id == requestId);
}
} }
private async Task<T> GetConfiguration() private async Task<T> GetConfiguration()
@ -181,11 +188,16 @@ namespace Ombi.Notifications.Interfaces
curlys.Setup(model, MovieRequest, Customization); curlys.Setup(model, MovieRequest, Customization);
} }
else else if (model.RequestType == RequestType.TvShow)
{ {
_log.LogDebug("Notification options: {@model}, Req: {@TvRequest}, Settings: {@Customization}", model, TvRequest, Customization); _log.LogDebug("Notification options: {@model}, Req: {@TvRequest}, Settings: {@Customization}", model, TvRequest, Customization);
curlys.Setup(model, TvRequest, Customization); curlys.Setup(model, TvRequest, Customization);
} }
else if (model.RequestType == RequestType.Album)
{
_log.LogDebug("Notification options: {@model}, Req: {@AlbumRequest}, Settings: {@Customization}", model, AlbumRequest, Customization);
curlys.Setup(model, AlbumRequest, Customization);
}
var parsed = resolver.ParseMessage(template, curlys); var parsed = resolver.ParseMessage(template, curlys);
return parsed; return parsed;

@ -47,14 +47,48 @@ namespace Ombi.Notifications
if (req?.RequestType == RequestType.Movie) if (req?.RequestType == RequestType.Movie)
{ {
PosterImage = string.Format((req?.PosterPath ?? string.Empty).StartsWith("/", StringComparison.InvariantCultureIgnoreCase) PosterImage = string.Format((req?.PosterPath ?? string.Empty).StartsWith("/", StringComparison.InvariantCultureIgnoreCase)
? "https://image.tmdb.org/t/p/w300{0}" : "https://image.tmdb.org/t/p/w300/{0}", req?.PosterPath); ? "https://image.tmdb.org/t/p/w300{0}" : "https://image.tmdb.org/t/p/w300/{0}", req?.PosterPath);
} }
else else
{ {
PosterImage = req?.PosterPath; PosterImage = req?.PosterPath;
} }
AdditionalInformation = opts?.AdditionalInformation ?? string.Empty;
}
public void Setup(NotificationOptions opts, AlbumRequest req, CustomizationSettings s)
{
LoadIssues(opts);
string title;
if (req == null)
{
opts.Substitutes.TryGetValue("Title", out title);
}
else
{
title = req?.Title;
}
ApplicationUrl = (s?.ApplicationUrl.HasValue() ?? false) ? s.ApplicationUrl : string.Empty;
ApplicationName = string.IsNullOrEmpty(s?.ApplicationName) ? "Ombi" : s?.ApplicationName;
RequestedUser = req?.RequestedUser?.UserName;
if (UserName.IsNullOrEmpty())
{
// Can be set if it's an issue
UserName = req?.RequestedUser?.UserName;
}
Alias = (req?.RequestedUser?.Alias.HasValue() ?? false) ? req?.RequestedUser?.Alias : req?.RequestedUser?.UserName;
Title = title;
RequestedDate = req?.RequestedDate.ToString("D");
if (Type.IsNullOrEmpty())
{
Type = req?.RequestType.Humanize();
}
Year = req?.ReleaseDate.Year.ToString();
PosterImage = (req?.Cover.HasValue() ?? false) ? req.Cover : req?.Disk ?? string.Empty;
AdditionalInformation = opts?.AdditionalInformation ?? string.Empty; AdditionalInformation = opts?.AdditionalInformation ?? string.Empty;
} }

@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Hangfire;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Ombi.Core.Notifications;
using Ombi.Helpers;
using Ombi.Notifications.Models;
using Ombi.Store.Entities;
using Ombi.Store.Entities.Requests;
using Ombi.Store.Repository;
using Ombi.Store.Repository.Requests;
namespace Ombi.Schedule.Jobs.Lidarr
{
public class LidarrAvailabilityChecker
{
public LidarrAvailabilityChecker(IMusicRequestRepository requests, IRepository<LidarrAlbumCache> albums, ILogger<LidarrAvailabilityChecker> log,
IBackgroundJobClient job, INotificationService notification)
{
_cachedAlbums = albums;
_requestRepository = requests;
_logger = log;
_job = job;
_notificationService = notification;
}
private readonly IMusicRequestRepository _requestRepository;
private readonly IRepository<LidarrAlbumCache> _cachedAlbums;
private readonly ILogger _logger;
private readonly IBackgroundJobClient _job;
private readonly INotificationService _notificationService;
public async Task Start()
{
var allAlbumRequests = _requestRepository.GetAll().Include(x => x.RequestedUser).Where(x => !x.Available);
var albumsToUpdate = new List<AlbumRequest>();
foreach (var request in allAlbumRequests)
{
// Check if we have it cached
var cachedAlbum = await _cachedAlbums.FirstOrDefaultAsync(x => x.ForeignAlbumId.Equals(request.ForeignAlbumId));
if (cachedAlbum != null)
{
if (cachedAlbum.Monitored && cachedAlbum.FullyAvailable)
{
request.Available = true;
request.MarkedAsAvailable = DateTime.Now;
albumsToUpdate.Add(request);
}
}
}
foreach (var albumRequest in albumsToUpdate)
{
await _requestRepository.Update(albumRequest);
var recipient = albumRequest.RequestedUser.Email.HasValue() ? albumRequest.RequestedUser.Email : string.Empty;
_logger.LogDebug("AlbumId: {0}, RequestUser: {1}", albumRequest.Id, recipient);
_job.Enqueue(() => _notificationService.Publish(new NotificationOptions
{
DateTime = DateTime.Now,
NotificationType = NotificationType.RequestAvailable,
RequestId = albumRequest.Id,
RequestType = RequestType.Album,
Recipient = recipient,
}));
}
}
}
}

@ -13,5 +13,10 @@ namespace Ombi.Store.Entities
public bool Monitored { get; set; } public bool Monitored { get; set; }
public string Title { get; set; } public string Title { get; set; }
public decimal PercentOfTracks { get; set; } public decimal PercentOfTracks { get; set; }
[NotMapped]
public bool PartiallyAvailable => PercentOfTracks != 100 && PercentOfTracks > 0;
[NotMapped]
public bool FullyAvailable => PercentOfTracks == 100;
} }
} }

@ -51,7 +51,7 @@
<a *ngIf="result.showSubscribe && result.subscribed" style="color:red" (click)="unSubscribe(result)" pTooltip="Unsubscribe notification"> <i class="fa fa-rss"></i></a> --> <a *ngIf="result.showSubscribe && result.subscribed" style="color:red" (click)="unSubscribe(result)" pTooltip="Unsubscribe notification"> <i class="fa fa-rss"></i></a> -->
</div> </div>
</div> </div>
<button style="text-align: right" class="btn btn-info-outline" (click)="viewAllAlbums()"> <button style="text-align: right" class="btn btn-info-outline" [disabled]="searchingAlbums" (click)="viewAllAlbums()">
<i class="fa fa-eye"></i> View Albums</button> <i class="fa fa-eye"></i> View Albums</button>
</div> </div>

@ -11,6 +11,7 @@ export class ArtistSearchComponent {
@Input() public result: ISearchArtistResult; @Input() public result: ISearchArtistResult;
@Input() public defaultPoster: string; @Input() public defaultPoster: string;
public searchingAlbums: boolean;
@Output() public viewAlbumsResult = new EventEmitter<ISearchAlbumResult[]>(); @Output() public viewAlbumsResult = new EventEmitter<ISearchAlbumResult[]>();
@ -18,6 +19,7 @@ export class ArtistSearchComponent {
} }
public viewAllAlbums() { public viewAllAlbums() {
this.searchingAlbums = true;
this.searchService.getAlbumsForArtist(this.result.forignArtistId).subscribe(x => { this.searchService.getAlbumsForArtist(this.result.forignArtistId).subscribe(x => {
this.viewAlbumsResult.emit(x); this.viewAlbumsResult.emit(x);
}); });

Loading…
Cancel
Save