Merge pull request #4340 from Ombi-app/partially-available-notifications

Partially available notifications
pull/4341/head
Jamie 3 years ago committed by GitHub
commit b32169806e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -55,23 +55,20 @@ jobs:
versioning: versioning:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [ build-ui, unit-test ]
outputs: outputs:
changelog: ${{ steps.changelog.outputs.clean_changelog }} changelog: ${{ steps.changelog.outputs.clean_changelog }}
tag: ${{ steps.changelog.outputs.tag }} tag: ${{ steps.changelog.outputs.tag }}
version: ${{ steps.changelog.outputs.version }} version: ${{ steps.changelog.outputs.version }}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
# This is only to get the next version number so we can set the version before compile
- name: Conventional Changelog Action - name: Conventional Changelog Action
id: changelog id: changelog
uses: TriPSs/conventional-changelog-action@v3 uses: TriPSs/conventional-changelog-action@v3
with: with:
skip-version-file: 'true' version-file: 'version.json'
skip-commit: 'true' skip-on-empty: 'false'
version-file: 'version.json' git-message: 'chore(release): :rocket: {version}'
output-file: 'false'
skip-on-empty: 'false'
git-push: 'false'
- name: Output version - name: Output version
run: | run: |
@ -162,14 +159,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Conventional Changelog Action
id: changelog
uses: TriPSs/conventional-changelog-action@v3
with:
version-file: 'version.json'
skip-on-empty: 'false'
git-message: 'chore(release): :rocket: {version}'
- name: Download Artifacts - name: Download Artifacts
id: download id: download
uses: actions/download-artifact@v2 uses: actions/download-artifact@v2
@ -192,9 +182,9 @@ jobs:
if: contains(github.ref, 'develop') if: contains(github.ref, 'develop')
with: with:
prerelease: true prerelease: true
body: ${{ steps.changelog.outputs.changelog }} body: ${{ needs.versioning.outputs.changelog }}
name: ${{ steps.changelog.outputs.tag }} name: ${{ needs.versioning.outputs.tag }}
tag_name: ${{ steps.changelog.outputs.tag }} tag_name: ${{ needs.versioning.outputs.tag }}
files: | files: |
artifacts/**/*.tar.gz artifacts/**/*.tar.gz
artifacts/**/*.zip artifacts/**/*.zip
@ -209,7 +199,7 @@ jobs:
url: 'https://api.github.com/repos/Ombi-app/Ombi.Apt/actions/workflows/build-deb.yml/dispatches' url: 'https://api.github.com/repos/Ombi-app/Ombi.Apt/actions/workflows/build-deb.yml/dispatches'
method: 'POST' method: 'POST'
contentType: 'application/json' contentType: 'application/json'
data: '{ "ref":"main", "inputs": { "version": "${{ steps.changelog.outputs.tag }}"} }' data: '{ "ref":"main", "inputs": { "version": "${{ needs.versioning.outputs.tag }}"} }'
customHeaders: "{'Accept':'application/vnd.github.v3+json', 'Authorization':'Bearer ${{secrets.APT_PAT}}', 'User-Agent':'Ombi'}" customHeaders: "{'Accept':'application/vnd.github.v3+json', 'Authorization':'Bearer ${{secrets.APT_PAT}}', 'User-Agent':'Ombi'}"

@ -14,5 +14,6 @@
IssueResolved = 9, IssueResolved = 9,
IssueComment = 10, IssueComment = 10,
Newsletter = 11, Newsletter = 11,
PartiallyAvailable = 12
} }
} }

@ -213,7 +213,51 @@ namespace Ombi.Notifications.Tests
[Test] [Test]
public void TvNotificationTests() public void TvNotificationTests()
{ {
var notificationOptions = new NotificationOptions(); var notificationOptions = new NotificationOptions
{
NotificationType = Helpers.NotificationType.PartiallyAvailable
};
var req = F.Build<ChildRequests>()
.With(x => x.RequestType, RequestType.TvShow)
.With(x => x.Available, true)
.Create();
var customization = new CustomizationSettings
{
ApplicationUrl = "url",
ApplicationName = "name"
};
var userPrefs = new UserNotificationPreferences();
sut.Setup(notificationOptions, req, customization, userPrefs);
Assert.That(req.Id.ToString(), Is.EqualTo(sut.RequestId));
Assert.That(req.ParentRequest.ExternalProviderId.ToString(), Is.EqualTo(sut.ProviderId));
Assert.That(req.ParentRequest.Title.ToString(), Is.EqualTo(sut.Title));
Assert.That(req.RequestedUser.UserName, Is.EqualTo(sut.RequestedUser));
Assert.That(req.RequestedUser.Alias, Is.EqualTo(sut.Alias));
Assert.That(req.RequestedDate.ToString("D"), Is.EqualTo(sut.RequestedDate));
Assert.That("TV Show", Is.EqualTo(sut.Type));
Assert.That(req.ParentRequest.Overview, Is.EqualTo(sut.Overview));
Assert.That(req.ParentRequest.ReleaseDate.Year.ToString(), Is.EqualTo(sut.Year));
Assert.That(req.DeniedReason, Is.EqualTo(sut.DenyReason));
Assert.That(req.MarkedAsAvailable?.ToString("D"), Is.EqualTo(sut.AvailableDate));
Assert.That("https://image.tmdb.org/t/p/w300/" + req.ParentRequest.PosterPath, Is.EqualTo(sut.PosterImage));
Assert.That(req.DeniedReason, Is.EqualTo(sut.DenyReason));
Assert.That(req.RequestedUser.Alias, Is.EqualTo(sut.UserPreference));
Assert.That(null, Is.EqualTo(sut.AdditionalInformation));
Assert.That("Available", Is.EqualTo(sut.RequestStatus));
Assert.That("url", Is.EqualTo(sut.ApplicationUrl));
Assert.That("name", Is.EqualTo(sut.ApplicationName));
}
[Test]
public void TvNotificationPartialAvailablilityTests()
{
var notificationOptions = new NotificationOptions {
NotificationType = Helpers.NotificationType.PartiallyAvailable
};
notificationOptions.Substitutes.Add("Season", "1");
notificationOptions.Substitutes.Add("Episodes", "1, 2");
var req = F.Build<ChildRequests>() var req = F.Build<ChildRequests>()
.With(x => x.RequestType, RequestType.TvShow) .With(x => x.RequestType, RequestType.TvShow)
.With(x => x.Available, true) .With(x => x.Available, true)
@ -244,6 +288,8 @@ namespace Ombi.Notifications.Tests
Assert.That("Available", Is.EqualTo(sut.RequestStatus)); Assert.That("Available", Is.EqualTo(sut.RequestStatus));
Assert.That("url", Is.EqualTo(sut.ApplicationUrl)); Assert.That("url", Is.EqualTo(sut.ApplicationUrl));
Assert.That("name", Is.EqualTo(sut.ApplicationName)); Assert.That("name", Is.EqualTo(sut.ApplicationName));
Assert.That(sut.PartiallyAvailableEpisodeNumbers, Is.EqualTo("1, 2"));
Assert.That(sut.PartiallyAvailableSeasonNumber, Is.EqualTo("1"));
} }
[Test] [Test]

@ -94,6 +94,10 @@ namespace Ombi.Notifications.Agents
{ {
await Run(model, settings, NotificationType.RequestAvailable); await Run(model, settings, NotificationType.RequestAvailable);
} }
protected override async Task PartiallyAvailable(NotificationOptions model, DiscordNotificationSettings settings)
{
await Run(model, settings, NotificationType.PartiallyAvailable);
}
protected override async Task Send(NotificationMessage model, DiscordNotificationSettings settings) protected override async Task Send(NotificationMessage model, DiscordNotificationSettings settings)
{ {
@ -166,8 +170,6 @@ namespace Ombi.Notifications.Agents
author.name = appName; author.name = appName;
} }
var embed = new DiscordEmbeds var embed = new DiscordEmbeds
{ {
fields = fields, fields = fields,

@ -219,6 +219,25 @@ namespace Ombi.Notifications.Agents
} }
protected override async Task PartiallyAvailable(NotificationOptions model, EmailNotificationSettings settings)
{
var message = await LoadTemplate(NotificationType.PartiallyAvailable, model, settings);
if (message == null)
{
return;
}
var plaintext = await LoadPlainTextMessage(NotificationType.PartiallyAvailable, model, settings);
message.Other.Add("PlainTextBody", plaintext);
await SendToSubscribers(settings, message);
message.To = model.RequestType == RequestType.Movie
? MovieRequest.RequestedUser.Email
: TvRequest.RequestedUser.Email;
await Send(message, settings);
}
protected override async Task RequestApproved(NotificationOptions model, EmailNotificationSettings settings) protected override async Task RequestApproved(NotificationOptions model, EmailNotificationSettings settings)
{ {
var message = await LoadTemplate(NotificationType.RequestApproved, model, settings); var message = await LoadTemplate(NotificationType.RequestApproved, model, settings);

@ -112,5 +112,10 @@ namespace Ombi.Notifications.Agents
await Send(notification, settings); await Send(notification, settings);
} }
protected override async Task PartiallyAvailable(NotificationOptions model, GotifySettings settings)
{
await Run(model, settings, NotificationType.PartiallyAvailable);
}
} }
} }

@ -316,5 +316,25 @@ namespace Ombi.Notifications.Agents
} }
} }
} }
protected override async Task PartiallyAvailable(NotificationOptions model, MobileNotificationSettings settings)
{
var parsed = await LoadTemplate(NotificationAgent.Mobile, NotificationType.PartiallyAvailable, model);
if (parsed.Disabled)
{
_logger.LogInformation($"Template {NotificationType.PartiallyAvailable} is disabled for {NotificationAgent.Mobile}");
return;
}
var notification = new NotificationMessage
{
Message = parsed.Message,
};
// Send to user
var playerIds = GetUsers(model, NotificationType.PartiallyAvailable);
await AddSubscribedUsers(playerIds);
await Send(playerIds, notification, settings, model);
}
} }
} }

@ -90,6 +90,10 @@ namespace Ombi.Notifications.Agents
{ {
await Run(model, settings, NotificationType.RequestAvailable); await Run(model, settings, NotificationType.RequestAvailable);
} }
protected override async Task PartiallyAvailable(NotificationOptions model, MattermostNotificationSettings settings)
{
await Run(model, settings, NotificationType.PartiallyAvailable);
}
protected override async Task Send(NotificationMessage model, MattermostNotificationSettings settings) protected override async Task Send(NotificationMessage model, MattermostNotificationSettings settings)
{ {

@ -359,5 +359,26 @@ namespace Ombi.Notifications.Agents
} }
} }
} }
protected override async Task PartiallyAvailable(NotificationOptions model, MobileNotificationSettings settings)
{
var parsed = await LoadTemplate(NotificationAgent.Mobile, NotificationType.PartiallyAvailable, model);
if (parsed.Disabled)
{
_logger.LogInformation($"Template {NotificationType.PartiallyAvailable} is disabled for {NotificationAgent.Mobile}");
return;
}
var notification = new NotificationMessage
{
Message = parsed.Message,
Subject = "New Request",
Data = GetNotificationData(parsed, NotificationType.PartiallyAvailable)
};
// Get admin devices
var playerIds = await GetAdmins(NotificationType.PartiallyAvailable);
await Send(playerIds, notification, settings, model, true);
}
} }
} }

@ -121,5 +121,10 @@ namespace Ombi.Notifications.Agents
await Send(notification, settings); await Send(notification, settings);
} }
protected override async Task PartiallyAvailable(NotificationOptions model, PushbulletSettings settings)
{
await Run(model, settings, NotificationType.PartiallyAvailable);
}
} }
} }

@ -121,5 +121,10 @@ namespace Ombi.Notifications.Agents
}; };
await Send(notification, settings); await Send(notification, settings);
} }
protected override async Task PartiallyAvailable(NotificationOptions model, PushoverSettings settings)
{
await Run(model, settings, NotificationType.PartiallyAvailable);
}
} }
} }

@ -138,5 +138,10 @@ namespace Ombi.Notifications.Agents
notification.Other.Add("image", parsed.Image); notification.Other.Add("image", parsed.Image);
await Send(notification, settings); await Send(notification, settings);
} }
protected override async Task PartiallyAvailable(NotificationOptions model, SlackNotificationSettings settings)
{
await Run(model, settings, NotificationType.PartiallyAvailable);
}
} }
} }

@ -115,5 +115,10 @@ namespace Ombi.Notifications.Agents
}; };
await Send(notification, settings); await Send(notification, settings);
} }
protected override async Task PartiallyAvailable(NotificationOptions model, TelegramSettings settings)
{
await Run(model, settings, NotificationType.PartiallyAvailable);
}
} }
} }

@ -119,5 +119,10 @@ namespace Ombi.Notifications.Agents
await Send(notification, settings); await Send(notification, settings);
} }
protected override async Task PartiallyAvailable(NotificationOptions model, WebhookSettings settings)
{
await Run(model, settings, NotificationType.PartiallyAvailable);
}
} }
} }

@ -123,5 +123,10 @@ namespace Ombi.Notifications.Agents
}; };
await Send(notification, settings); await Send(notification, settings);
} }
protected override async Task PartiallyAvailable(NotificationOptions model, TwilioSettings settings)
{
await Run(model, settings, NotificationType.PartiallyAvailable);
}
} }
} }

@ -110,6 +110,15 @@ namespace Ombi.Notifications
case NotificationType.IssueComment: case NotificationType.IssueComment:
await IssueComment(model, notificationSettings); await IssueComment(model, notificationSettings);
break; break;
case NotificationType.AdminNote:
break;
case NotificationType.WelcomeEmail:
break;
case NotificationType.Newsletter:
break;
case NotificationType.PartiallyAvailable:
await PartiallyAvailable(model, notificationSettings);
break;
default: default:
throw new ArgumentOutOfRangeException(); throw new ArgumentOutOfRangeException();
} }
@ -236,6 +245,7 @@ namespace Ombi.Notifications
protected abstract Task RequestDeclined(NotificationOptions model, T settings); protected abstract Task RequestDeclined(NotificationOptions model, T settings);
protected abstract Task RequestApproved(NotificationOptions model, T settings); protected abstract Task RequestApproved(NotificationOptions model, T settings);
protected abstract Task AvailableRequest(NotificationOptions model, T settings); protected abstract Task AvailableRequest(NotificationOptions model, T settings);
protected abstract Task PartiallyAvailable(NotificationOptions model, T settings);
protected abstract Task Send(NotificationMessage model, T settings); protected abstract Task Send(NotificationMessage model, T settings);
protected abstract Task Test(NotificationOptions model, T settings); protected abstract Task Test(NotificationOptions model, T settings);
} }

@ -33,7 +33,7 @@ namespace Ombi.Notifications
UserNotificationPreferences pref) UserNotificationPreferences pref)
{ {
LoadIssues(opts); LoadIssues(opts);
LoadCommon(req, s, pref); LoadCommon(req, s, pref, opts);
LoadTitle(opts, req); LoadTitle(opts, req);
ProviderId = req?.TheMovieDbId.ToString() ?? string.Empty; ProviderId = req?.TheMovieDbId.ToString() ?? string.Empty;
Year = req?.ReleaseDate.Year.ToString(); Year = req?.ReleaseDate.Year.ToString();
@ -47,7 +47,7 @@ namespace Ombi.Notifications
UserNotificationPreferences pref) UserNotificationPreferences pref)
{ {
LoadIssues(opts); LoadIssues(opts);
LoadCommon(req, s, pref); LoadCommon(req, s, pref, opts);
LoadTitle(opts, req); LoadTitle(opts, req);
ProviderId = req?.ParentRequest?.ExternalProviderId.ToString() ?? string.Empty; ProviderId = req?.ParentRequest?.ExternalProviderId.ToString() ?? string.Empty;
Year = req?.ParentRequest?.ReleaseDate.Year.ToString(); Year = req?.ParentRequest?.ReleaseDate.Year.ToString();
@ -83,7 +83,7 @@ namespace Ombi.Notifications
UserNotificationPreferences pref) UserNotificationPreferences pref)
{ {
LoadIssues(opts); LoadIssues(opts);
LoadCommon(req, s, pref); LoadCommon(req, s, pref, opts);
LoadTitle(opts, req); LoadTitle(opts, req);
ProviderId = req?.ForeignArtistId ?? string.Empty; ProviderId = req?.ForeignArtistId ?? string.Empty;
Year = req?.ReleaseDate.Year.ToString(); Year = req?.ReleaseDate.Year.ToString();
@ -106,7 +106,7 @@ namespace Ombi.Notifications
: string.Empty; : string.Empty;
} }
private void LoadCommon(BaseRequest req, CustomizationSettings s, UserNotificationPreferences pref) private void LoadCommon(BaseRequest req, CustomizationSettings s, UserNotificationPreferences pref, NotificationOptions opts)
{ {
ApplicationName = string.IsNullOrEmpty(s?.ApplicationName) ? "Ombi" : s.ApplicationName; ApplicationName = string.IsNullOrEmpty(s?.ApplicationName) ? "Ombi" : s.ApplicationName;
ApplicationUrl = s?.ApplicationUrl.HasValue() ?? false ? s.ApplicationUrl : string.Empty; ApplicationUrl = s?.ApplicationUrl.HasValue() ?? false ? s.ApplicationUrl : string.Empty;
@ -137,6 +137,18 @@ namespace Ombi.Notifications
{ {
UserPreference = pref.Value.HasValue() ? pref.Value : Alias; UserPreference = pref.Value.HasValue() ? pref.Value : Alias;
} }
if (opts.NotificationType == NotificationType.PartiallyAvailable)
{
if (opts.Substitutes.TryGetValue("Season", out var sNumber))
{
PartiallyAvailableSeasonNumber = sNumber;
}
if (opts.Substitutes.TryGetValue("Episodes", out var epNumber))
{
PartiallyAvailableEpisodeNumbers = epNumber;
}
}
} }
private static string HumanizeReturnType(RequestType? requestType) private static string HumanizeReturnType(RequestType? requestType)
@ -220,6 +232,8 @@ namespace Ombi.Notifications
public string AvailableDate { get; set; } public string AvailableDate { get; set; }
public string RequestStatus { get; set; } public string RequestStatus { get; set; }
public string ProviderId { get; set; } public string ProviderId { get; set; }
public string PartiallyAvailableEpisodeNumbers { get; set; }
public string PartiallyAvailableSeasonNumber { get; set; }
// System Defined // System Defined
private string LongDate => DateTime.Now.ToString("D"); private string LongDate => DateTime.Now.ToString("D");
@ -259,6 +273,8 @@ namespace Ombi.Notifications
{ nameof(AvailableDate), AvailableDate }, { nameof(AvailableDate), AvailableDate },
{ nameof(RequestStatus), RequestStatus }, { nameof(RequestStatus), RequestStatus },
{ nameof(ProviderId), ProviderId }, { nameof(ProviderId), ProviderId },
{ nameof(PartiallyAvailableEpisodeNumbers), PartiallyAvailableEpisodeNumbers },
{ nameof(PartiallyAvailableSeasonNumber), PartiallyAvailableSeasonNumber },
}; };
} }
} }

@ -154,24 +154,19 @@ namespace Ombi.Schedule.Jobs.Radarr
{ {
availableEpisode.Add(new AvailabilityModel availableEpisode.Add(new AvailabilityModel
{ {
Id = episode.Id Id = episode.Id,
EpisodeNumber = episode.EpisodeNumber,
SeasonNumber = episode.Season.SeasonNumber
}); });
episode.Available = true; episode.Available = true;
} }
} }
} }
//TODO Partial avilability notifications here
if (availableEpisode.Any()) if (availableEpisode.Any())
{ {
//await _hub.Clients.Clients(NotificationHub.AdminConnectionIds)
// .SendAsync(NotificationHub.NotificationEvent, "Sonarr Availability Checker found some new available episodes!");
await _tvRequest.Save(); await _tvRequest.Save();
} }
//foreach(var c in availableEpisode)
//{
// await _tvRepo.MarkEpisodeAsAvailable(c.Id);
//}
// Check to see if all of the episodes in all seasons are available for this request // Check to see if all of the episodes in all seasons are available for this request
var allAvailable = child.SeasonRequests.All(x => x.Episodes.All(c => c.Available)); var allAvailable = child.SeasonRequests.All(x => x.Episodes.All(c => c.Available));
@ -193,6 +188,20 @@ namespace Ombi.Schedule.Jobs.Radarr
Recipient = child.RequestedUser.Email Recipient = child.RequestedUser.Email
}); });
} }
else if (availableEpisode.Any())
{
var notification = new NotificationOptions
{
DateTime = DateTime.Now,
NotificationType = NotificationType.PartiallyAvailable,
RequestId = child.Id,
RequestType = RequestType.TvShow,
Recipient = child.RequestedUser.Email,
};
notification.Substitutes.Add("Season", availableEpisode.First().SeasonNumber.ToString());
notification.Substitutes.Add("Episodes", string.Join(", ", availableEpisode.Select(x => x.EpisodeNumber)));
await _notification.Notify(notification);
}
} }
await _tvRequest.Save(); await _tvRequest.Save();

@ -1,10 +1,10 @@
using Ombi.Store.Entities; namespace Ombi.Schedule.Jobs
namespace Ombi.Schedule.Jobs.Plex.Models
{ {
public class AvailabilityModel public class AvailabilityModel
{ {
public int Id { get; set; } public int Id { get; set; }
public int SeasonNumber { get; set; }
public int EpisodeNumber { get; set; }
public string RequestedUser { get; set; } public string RequestedUser { get; set; }
} }
} }

@ -1,31 +1,5 @@
#region Copyright using System;
// /************************************************************************ using System.Collections.Generic;
// Copyright (c) 2017 Jamie Rees
// File: EmbyAvaliabilityCheker.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
@ -173,6 +147,7 @@ namespace Ombi.Schedule.Jobs.Emby
x.Series.Title == child.Title); x.Series.Title == child.Title);
} }
var availableEpisode = new List<AvailabilityModel>();
foreach (var season in child.SeasonRequests) foreach (var season in child.SeasonRequests)
{ {
foreach (var episode in season.Episodes) foreach (var episode in season.Episodes)
@ -188,11 +163,22 @@ namespace Ombi.Schedule.Jobs.Emby
if (foundEp != null) if (foundEp != null)
{ {
availableEpisode.Add(new AvailabilityModel
{
Id = episode.Id,
EpisodeNumber = episode.EpisodeNumber,
SeasonNumber = episode.Season.SeasonNumber
});
episode.Available = true; episode.Available = true;
} }
} }
} }
if (availableEpisode.Any())
{
await _tvRepo.Save();
}
// Check to see if all of the episodes in all seasons are available for this request // Check to see if all of the episodes in all seasons are available for this request
var allAvailable = child.SeasonRequests.All(x => x.Episodes.All(c => c.Available)); var allAvailable = child.SeasonRequests.All(x => x.Episodes.All(c => c.Available));
if (allAvailable) if (allAvailable)
@ -209,6 +195,20 @@ namespace Ombi.Schedule.Jobs.Emby
Recipient = child.RequestedUser.Email Recipient = child.RequestedUser.Email
}); });
} }
else if (availableEpisode.Any())
{
var notification = new NotificationOptions
{
DateTime = DateTime.Now,
NotificationType = NotificationType.PartiallyAvailable,
RequestId = child.Id,
RequestType = RequestType.TvShow,
Recipient = child.RequestedUser.Email,
};
notification.Substitutes.Add("Season", availableEpisode.First().SeasonNumber.ToString());
notification.Substitutes.Add("Episodes", string.Join(", ", availableEpisode.Select(x => x.EpisodeNumber)));
await _notificationService.Notify(notification);
}
} }
await _tvRepo.Save(); await _tvRepo.Save();

@ -26,6 +26,7 @@
#endregion #endregion
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
@ -173,6 +174,7 @@ namespace Ombi.Schedule.Jobs.Jellyfin
x.Series.Title == child.Title); x.Series.Title == child.Title);
} }
var availableEpisode = new List<AvailabilityModel>();
foreach (var season in child.SeasonRequests) foreach (var season in child.SeasonRequests)
{ {
foreach (var episode in season.Episodes) foreach (var episode in season.Episodes)
@ -188,11 +190,22 @@ namespace Ombi.Schedule.Jobs.Jellyfin
if (foundEp != null) if (foundEp != null)
{ {
availableEpisode.Add(new AvailabilityModel
{
Id = episode.Id,
EpisodeNumber = episode.EpisodeNumber,
SeasonNumber = episode.Season.SeasonNumber
});
episode.Available = true; episode.Available = true;
} }
} }
} }
if (availableEpisode.Any())
{
await _tvRepo.Save();
}
// Check to see if all of the episodes in all seasons are available for this request // Check to see if all of the episodes in all seasons are available for this request
var allAvailable = child.SeasonRequests.All(x => x.Episodes.All(c => c.Available)); var allAvailable = child.SeasonRequests.All(x => x.Episodes.All(c => c.Available));
if (allAvailable) if (allAvailable)
@ -209,6 +222,20 @@ namespace Ombi.Schedule.Jobs.Jellyfin
Recipient = child.RequestedUser.Email Recipient = child.RequestedUser.Email
}); });
} }
else if (availableEpisode.Any())
{
var notification = new NotificationOptions
{
DateTime = DateTime.Now,
NotificationType = NotificationType.PartiallyAvailable,
RequestId = child.Id,
RequestType = RequestType.TvShow,
Recipient = child.RequestedUser.Email,
};
notification.Substitutes.Add("Season", availableEpisode.First().SeasonNumber.ToString());
notification.Substitutes.Add("Episodes", string.Join(", ", availableEpisode.Select(x => x.EpisodeNumber)));
await _notificationService.Notify(notification);
}
} }
await _tvRepo.Save(); await _tvRepo.Save();

@ -127,22 +127,19 @@ namespace Ombi.Schedule.Jobs.Plex
{ {
availableEpisode.Add(new AvailabilityModel availableEpisode.Add(new AvailabilityModel
{ {
Id = episode.Id Id = episode.Id,
EpisodeNumber = episode.EpisodeNumber,
SeasonNumber = episode.Season.SeasonNumber
}); });
episode.Available = true; episode.Available = true;
} }
} }
} }
//TODO Partial avilability notifications here
if (availableEpisode.Any()) if (availableEpisode.Any())
{ {
await _tvRepo.Save(); await _tvRepo.Save();
} }
//foreach(var c in availableEpisode)
//{
// await _tvRepo.MarkEpisodeAsAvailable(c.Id);
//}
// Check to see if all of the episodes in all seasons are available for this request // Check to see if all of the episodes in all seasons are available for this request
var allAvailable = child.SeasonRequests.All(x => x.Episodes.All(c => c.Available)); var allAvailable = child.SeasonRequests.All(x => x.Episodes.All(c => c.Available));
@ -162,6 +159,20 @@ namespace Ombi.Schedule.Jobs.Plex
Recipient = child.RequestedUser.Email Recipient = child.RequestedUser.Email
}); });
} }
else if (availableEpisode.Any())
{
var notification = new NotificationOptions
{
DateTime = DateTime.Now,
NotificationType = NotificationType.PartiallyAvailable,
RequestId = child.Id,
RequestType = RequestType.TvShow,
Recipient = child.RequestedUser.Email,
};
notification.Substitutes.Add("Season", availableEpisode.First().SeasonNumber.ToString());
notification.Substitutes.Add("Episodes", string.Join(", " ,availableEpisode.Select(x => x.EpisodeNumber)));
await _notificationService.Notify(notification);
}
} }
await _tvRepo.Save(); await _tvRepo.Save();

@ -208,6 +208,16 @@ namespace Ombi.Store.Context
Enabled = true, Enabled = true,
}; };
break; break;
case NotificationType.PartiallyAvailable:
notificationToAdd = new NotificationTemplates
{
NotificationType = notificationType,
Message = "Your TV request is now partially available! Season {PartiallyAvailableSeasonNumber} Episodes {PartiallyAvailableEpisodeNumbers}!",
Subject = "{ApplicationName}: Partially Available Request!",
Agent = agent,
Enabled = true,
};
break;
default: default:
throw new ArgumentOutOfRangeException(); throw new ArgumentOutOfRangeException();
} }

@ -13,6 +13,8 @@
"discord.enabled": true, "discord.enabled": true,
"conventionalCommits.scopes": [ "conventionalCommits.scopes": [
"discover", "discover",
"request-limits" "request-limits",
"notifications",
"settings"
] ]
} }

@ -52,7 +52,7 @@ export enum NotificationType {
IssueResolved = 9, IssueResolved = 9,
IssueComment = 10, IssueComment = 10,
Newsletter = 11, Newsletter = 11,
WhatsApp = 12, PartiallyAvailable = 12,
} }
export interface IDiscordNotifcationSettings extends INotificationSettings { export interface IDiscordNotifcationSettings extends INotificationSettings {

@ -63,6 +63,7 @@ export class PlexComponent implements OnInit, OnDestroy {
server.plexAuthToken = selectedServer.accessToken; server.plexAuthToken = selectedServer.accessToken;
server.port = parseInt(selectedServer.port); server.port = parseInt(selectedServer.port);
server.ssl = selectedServer.scheme === "http" ? false : true; server.ssl = selectedServer.scheme === "http" ? false : true;
server.serverHostname = "";
this.notificationService.success(`Selected ${server.name}!`); this.notificationService.success(`Selected ${server.name}!`);
} }
@ -128,7 +129,7 @@ export class PlexComponent implements OnInit, OnDestroy {
let invalid = false; let invalid = false;
this.settings.servers.forEach(server => { this.settings.servers.forEach(server => {
if (server.serverHostname.length > 0 && !server.serverHostname.startsWith("http")) { if (server.serverHostname && server.serverHostname.length > 0 && !server.serverHostname.startsWith("http")) {
invalid = true; invalid = true;
} }
}); });

Loading…
Cancel
Save