mirror of https://github.com/lidarr/Lidarr
New: Notifications when Manual Interaction is required for importing
(cherry picked from commit 33c7bd54b222c54ed7e505653793ddf962617d52)
This commit is contained in:
parent
a3c33fe8cc
commit
e0ffb7d359
|
@ -67,6 +67,7 @@ class Notification extends Component {
|
|||
onImportFailure,
|
||||
onTrackRetag,
|
||||
onApplicationUpdate,
|
||||
onManualInteractionRequired,
|
||||
supportsOnGrab,
|
||||
supportsOnReleaseImport,
|
||||
supportsOnUpgrade,
|
||||
|
@ -78,7 +79,8 @@ class Notification extends Component {
|
|||
supportsOnDownloadFailure,
|
||||
supportsOnImportFailure,
|
||||
supportsOnTrackRetag,
|
||||
supportsOnApplicationUpdate
|
||||
supportsOnApplicationUpdate,
|
||||
supportsOnManualInteractionRequired
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
|
@ -177,14 +179,22 @@ class Notification extends Component {
|
|||
}
|
||||
|
||||
{
|
||||
!onGrab && !onReleaseImport && !onRename && !onTrackRetag && !onAlbumDelete && !onArtistDelete &&
|
||||
!onHealthIssue && !onHealthRestored && !onDownloadFailure && !onImportFailure && !onApplicationUpdate &&
|
||||
supportsOnManualInteractionRequired && onManualInteractionRequired ?
|
||||
<Label kind={kinds.SUCCESS}>
|
||||
{translate('OnManualInteractionRequired')}
|
||||
</Label> :
|
||||
null
|
||||
}
|
||||
|
||||
{
|
||||
!onGrab && !onReleaseImport && !onRename && !onTrackRetag && !onAlbumDelete && !onArtistDelete && !onHealthIssue && !onHealthRestored && !onDownloadFailure && !onImportFailure && !onApplicationUpdate && !onManualInteractionRequired ?
|
||||
<Label
|
||||
kind={kinds.DISABLED}
|
||||
outline={true}
|
||||
>
|
||||
{translate('Disabled')}
|
||||
</Label>
|
||||
</Label> :
|
||||
null
|
||||
}
|
||||
|
||||
<EditNotificationModalConnector
|
||||
|
@ -223,6 +233,7 @@ Notification.propTypes = {
|
|||
onImportFailure: PropTypes.bool.isRequired,
|
||||
onTrackRetag: PropTypes.bool.isRequired,
|
||||
onApplicationUpdate: PropTypes.bool.isRequired,
|
||||
onManualInteractionRequired: PropTypes.bool.isRequired,
|
||||
supportsOnGrab: PropTypes.bool.isRequired,
|
||||
supportsOnReleaseImport: PropTypes.bool.isRequired,
|
||||
supportsOnUpgrade: PropTypes.bool.isRequired,
|
||||
|
@ -235,6 +246,7 @@ Notification.propTypes = {
|
|||
supportsOnImportFailure: PropTypes.bool.isRequired,
|
||||
supportsOnTrackRetag: PropTypes.bool.isRequired,
|
||||
supportsOnApplicationUpdate: PropTypes.bool.isRequired,
|
||||
supportsOnManualInteractionRequired: PropTypes.bool.isRequired,
|
||||
onConfirmDeleteNotification: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ function NotificationEventItems(props) {
|
|||
onImportFailure,
|
||||
onTrackRetag,
|
||||
onApplicationUpdate,
|
||||
onManualInteractionRequired,
|
||||
supportsOnGrab,
|
||||
supportsOnReleaseImport,
|
||||
supportsOnUpgrade,
|
||||
|
@ -39,7 +40,8 @@ function NotificationEventItems(props) {
|
|||
supportsOnDownloadFailure,
|
||||
supportsOnImportFailure,
|
||||
supportsOnTrackRetag,
|
||||
supportsOnApplicationUpdate
|
||||
supportsOnApplicationUpdate,
|
||||
supportsOnManualInteractionRequired
|
||||
} = item;
|
||||
|
||||
return (
|
||||
|
@ -201,6 +203,17 @@ function NotificationEventItems(props) {
|
|||
/>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div>
|
||||
<FormInputGroup
|
||||
type={inputTypes.CHECK}
|
||||
name="onManualInteractionRequired"
|
||||
helpText={translate('OnManualInteractionRequiredHelpText')}
|
||||
isDisabled={!supportsOnManualInteractionRequired.value}
|
||||
{...onManualInteractionRequired}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</FormGroup>
|
||||
|
|
|
@ -111,6 +111,7 @@ export default {
|
|||
selectedSchema.onImportFailure = selectedSchema.supportsOnImportFailure;
|
||||
selectedSchema.onTrackRetag = selectedSchema.supportsOnTrackRetag;
|
||||
selectedSchema.onApplicationUpdate = selectedSchema.supportsOnApplicationUpdate;
|
||||
selectedSchema.onManualInteractionRequired = selectedSchema.supportsOnManualInteractionRequired;
|
||||
|
||||
return selectedSchema;
|
||||
});
|
||||
|
|
|
@ -17,6 +17,7 @@ namespace Lidarr.Api.V1.Notifications
|
|||
public bool OnImportFailure { get; set; }
|
||||
public bool OnTrackRetag { get; set; }
|
||||
public bool OnApplicationUpdate { get; set; }
|
||||
public bool OnManualInteractionRequired { get; set; }
|
||||
public bool SupportsOnGrab { get; set; }
|
||||
public bool SupportsOnReleaseImport { get; set; }
|
||||
public bool SupportsOnUpgrade { get; set; }
|
||||
|
@ -30,6 +31,7 @@ namespace Lidarr.Api.V1.Notifications
|
|||
public bool SupportsOnImportFailure { get; set; }
|
||||
public bool SupportsOnTrackRetag { get; set; }
|
||||
public bool SupportsOnApplicationUpdate { get; set; }
|
||||
public bool SupportsOnManualInteractionRequired { get; set; }
|
||||
public string TestCommand { get; set; }
|
||||
}
|
||||
|
||||
|
@ -56,6 +58,7 @@ namespace Lidarr.Api.V1.Notifications
|
|||
resource.OnImportFailure = definition.OnImportFailure;
|
||||
resource.OnTrackRetag = definition.OnTrackRetag;
|
||||
resource.OnApplicationUpdate = definition.OnApplicationUpdate;
|
||||
resource.OnManualInteractionRequired = definition.OnManualInteractionRequired;
|
||||
resource.SupportsOnGrab = definition.SupportsOnGrab;
|
||||
resource.SupportsOnReleaseImport = definition.SupportsOnReleaseImport;
|
||||
resource.SupportsOnUpgrade = definition.SupportsOnUpgrade;
|
||||
|
@ -69,6 +72,7 @@ namespace Lidarr.Api.V1.Notifications
|
|||
resource.SupportsOnImportFailure = definition.SupportsOnImportFailure;
|
||||
resource.SupportsOnTrackRetag = definition.SupportsOnTrackRetag;
|
||||
resource.SupportsOnApplicationUpdate = definition.SupportsOnApplicationUpdate;
|
||||
resource.SupportsOnManualInteractionRequired = definition.SupportsOnManualInteractionRequired;
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
@ -94,6 +98,7 @@ namespace Lidarr.Api.V1.Notifications
|
|||
definition.OnImportFailure = resource.OnImportFailure;
|
||||
definition.OnTrackRetag = resource.OnTrackRetag;
|
||||
definition.OnApplicationUpdate = resource.OnApplicationUpdate;
|
||||
definition.OnManualInteractionRequired = resource.OnManualInteractionRequired;
|
||||
definition.SupportsOnGrab = resource.SupportsOnGrab;
|
||||
definition.SupportsOnReleaseImport = resource.SupportsOnReleaseImport;
|
||||
definition.SupportsOnUpgrade = resource.SupportsOnUpgrade;
|
||||
|
@ -107,6 +112,7 @@ namespace Lidarr.Api.V1.Notifications
|
|||
definition.SupportsOnImportFailure = resource.SupportsOnImportFailure;
|
||||
definition.SupportsOnTrackRetag = resource.SupportsOnTrackRetag;
|
||||
definition.SupportsOnApplicationUpdate = resource.SupportsOnApplicationUpdate;
|
||||
definition.SupportsOnManualInteractionRequired = resource.SupportsOnManualInteractionRequired;
|
||||
|
||||
return definition;
|
||||
}
|
||||
|
|
|
@ -50,8 +50,8 @@ namespace NzbDrone.Core.Test.Download.CompletedDownloadServiceTests
|
|||
.Returns((DownloadClientItem item, DownloadClientItem previous) => item);
|
||||
|
||||
Mocker.GetMock<IHistoryService>()
|
||||
.Setup(s => s.MostRecentForDownloadId(_trackedDownload.DownloadItem.DownloadId))
|
||||
.Returns(new EntityHistory());
|
||||
.Setup(s => s.FindByDownloadId(_trackedDownload.DownloadItem.DownloadId))
|
||||
.Returns(new List<EntityHistory>());
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(s => s.GetArtist("Drone.S01E01.HDTV"))
|
||||
|
@ -70,8 +70,8 @@ namespace NzbDrone.Core.Test.Download.CompletedDownloadServiceTests
|
|||
private void GivenNoGrabbedHistory()
|
||||
{
|
||||
Mocker.GetMock<IHistoryService>()
|
||||
.Setup(s => s.MostRecentForDownloadId(_trackedDownload.DownloadItem.DownloadId))
|
||||
.Returns((EntityHistory)null);
|
||||
.Setup(s => s.FindByDownloadId(_trackedDownload.DownloadItem.DownloadId))
|
||||
.Returns(new List<EntityHistory>());
|
||||
}
|
||||
|
||||
private void GivenArtistMatch()
|
||||
|
@ -86,8 +86,11 @@ namespace NzbDrone.Core.Test.Download.CompletedDownloadServiceTests
|
|||
_trackedDownload.DownloadItem.DownloadId = "1234";
|
||||
_trackedDownload.DownloadItem.Title = "Droned Pilot"; // Set a badly named download
|
||||
Mocker.GetMock<IHistoryService>()
|
||||
.Setup(s => s.MostRecentForDownloadId(It.Is<string>(i => i == "1234")))
|
||||
.Returns(new EntityHistory() { SourceTitle = "Droned S01E01" });
|
||||
.Setup(s => s.FindByDownloadId(It.Is<string>(i => i == "1234")))
|
||||
.Returns(new List<EntityHistory>
|
||||
{
|
||||
new EntityHistory() { SourceTitle = "Droned S01E01", EventType = EntityHistoryEventType.Grabbed }
|
||||
});
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.Setup(s => s.GetArtist(It.IsAny<string>()))
|
||||
|
@ -151,9 +154,6 @@ namespace NzbDrone.Core.Test.Download.CompletedDownloadServiceTests
|
|||
GivenABadlyNamedDownload();
|
||||
_trackedDownload.RemoteAlbum.Artist = null;
|
||||
|
||||
Mocker.GetMock<IHistoryService>()
|
||||
.Setup(s => s.MostRecentForDownloadId(It.Is<string>(i => i == "1234")));
|
||||
|
||||
Subject.Check(_trackedDownload);
|
||||
|
||||
AssertNotReadyToImport();
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
// using System.Collections.Generic;
|
||||
// using System.Linq;
|
||||
// using FizzWare.NBuilder;
|
||||
// using FluentAssertions;
|
||||
// using Moq;
|
||||
// using NUnit.Framework;
|
||||
// using NzbDrone.Common.Extensions;
|
||||
// using NzbDrone.Core.Download;
|
||||
// using NzbDrone.Core.History;
|
||||
// using NzbDrone.Core.MediaFiles.EpisodeImport.Specifications;
|
||||
// using NzbDrone.Core.Music;
|
||||
// using NzbDrone.Core.Parser.Model;
|
||||
// using NzbDrone.Core.Test.Framework;
|
||||
// using NzbDrone.Test.Common;
|
||||
//
|
||||
// namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
||||
// {
|
||||
// [TestFixture]
|
||||
// public class MatchesGrabSpecificationFixture : CoreTest<MatchesGrabSpecification>
|
||||
// {
|
||||
// private Episode _episode1;
|
||||
// private Episode _episode2;
|
||||
// private Episode _episode3;
|
||||
// private LocalEpisode _localEpisode;
|
||||
// private DownloadClientItem _downloadClientItem;
|
||||
//
|
||||
// [SetUp]
|
||||
// public void Setup()
|
||||
// {
|
||||
// _episode1 = Builder<Episode>.CreateNew()
|
||||
// .With(e => e.Id = 1)
|
||||
// .Build();
|
||||
//
|
||||
// _episode2 = Builder<Episode>.CreateNew()
|
||||
// .With(e => e.Id = 2)
|
||||
// .Build();
|
||||
//
|
||||
// _episode3 = Builder<Episode>.CreateNew()
|
||||
// .With(e => e.Id = 3)
|
||||
// .Build();
|
||||
//
|
||||
// _localEpisode = Builder<LocalEpisode>.CreateNew()
|
||||
// .With(l => l.Path = @"C:\Test\Unsorted\Series.Title.S01E01.720p.HDTV-Sonarr\S01E05.mkv".AsOsAgnostic())
|
||||
// .With(l => l.Episodes = new List<Episode> { _episode1 })
|
||||
// .With(l => l.Release = null)
|
||||
// .Build();
|
||||
//
|
||||
// _downloadClientItem = Builder<DownloadClientItem>.CreateNew().Build();
|
||||
// }
|
||||
//
|
||||
// private void GivenHistoryForEpisodes(params Episode[] episodes)
|
||||
// {
|
||||
// if (episodes.Empty())
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// var grabbedHistories = Builder<EpisodeHistory>.CreateListOfSize(episodes.Length)
|
||||
// .All()
|
||||
// .With(h => h.EventType == EpisodeHistoryEventType.Grabbed)
|
||||
// .BuildList();
|
||||
//
|
||||
// for (var i = 0; i < grabbedHistories.Count; i++)
|
||||
// {
|
||||
// grabbedHistories[i].EpisodeId = episodes[i].Id;
|
||||
// }
|
||||
//
|
||||
// _localEpisode.Release = new GrabbedReleaseInfo(grabbedHistories);
|
||||
// }
|
||||
//
|
||||
// [Test]
|
||||
// public void should_be_accepted_for_existing_file()
|
||||
// {
|
||||
// _localEpisode.ExistingFile = true;
|
||||
//
|
||||
// Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||
// }
|
||||
//
|
||||
// [Test]
|
||||
// public void should_be_accepted_if_no_download_client_item()
|
||||
// {
|
||||
// Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||
// }
|
||||
//
|
||||
// [Test]
|
||||
// public void should_be_accepted_if_no_grabbed_release_info()
|
||||
// {
|
||||
// GivenHistoryForEpisodes();
|
||||
//
|
||||
// Subject.IsSatisfiedBy(_localEpisode, _downloadClientItem).Accepted.Should().BeTrue();
|
||||
// }
|
||||
//
|
||||
// [Test]
|
||||
// public void should_be_accepted_if_file_episode_matches_single_grabbed_release_info()
|
||||
// {
|
||||
// GivenHistoryForEpisodes(_episode1);
|
||||
//
|
||||
// Subject.IsSatisfiedBy(_localEpisode, _downloadClientItem).Accepted.Should().BeTrue();
|
||||
// }
|
||||
//
|
||||
// [Test]
|
||||
// public void should_be_accepted_if_file_episode_is_in_multi_episode_grabbed_release_info()
|
||||
// {
|
||||
// GivenHistoryForEpisodes(_episode1, _episode2);
|
||||
//
|
||||
// Subject.IsSatisfiedBy(_localEpisode, _downloadClientItem).Accepted.Should().BeTrue();
|
||||
// }
|
||||
//
|
||||
// [Test]
|
||||
// public void should_be_rejected_if_file_episode_does_not_match_single_grabbed_release_info()
|
||||
// {
|
||||
// GivenHistoryForEpisodes(_episode2);
|
||||
//
|
||||
// Subject.IsSatisfiedBy(_localEpisode, _downloadClientItem).Accepted.Should().BeFalse();
|
||||
// }
|
||||
//
|
||||
// [Test]
|
||||
// public void should_be_rejected_if_file_episode_is_not_in_multi_episode_grabbed_release_info()
|
||||
// {
|
||||
// GivenHistoryForEpisodes(_episode2, _episode3);
|
||||
//
|
||||
// Subject.IsSatisfiedBy(_localEpisode, _downloadClientItem).Accepted.Should().BeFalse();
|
||||
// }
|
||||
// }
|
||||
// }
|
|
@ -103,6 +103,11 @@ namespace NzbDrone.Core.Test.NotificationTests
|
|||
{
|
||||
TestLogger.Info("OnApplicationUpdate was called");
|
||||
}
|
||||
|
||||
public override void OnManualInteractionRequired(ManualInteractionRequiredMessage message)
|
||||
{
|
||||
TestLogger.Info("OnManualInteractionRequired was called");
|
||||
}
|
||||
}
|
||||
|
||||
private class TestNotificationWithNoEvents : NotificationBase<TestSetting>
|
||||
|
@ -143,6 +148,7 @@ namespace NzbDrone.Core.Test.NotificationTests
|
|||
notification.SupportsOnImportFailure.Should().BeTrue();
|
||||
notification.SupportsOnTrackRetag.Should().BeTrue();
|
||||
notification.SupportsOnApplicationUpdate.Should().BeTrue();
|
||||
notification.SupportsOnManualInteractionRequired.Should().BeTrue();
|
||||
notification.SupportsOnAlbumDelete.Should().BeTrue();
|
||||
notification.SupportsOnArtistDelete.Should().BeTrue();
|
||||
}
|
||||
|
@ -162,6 +168,7 @@ namespace NzbDrone.Core.Test.NotificationTests
|
|||
notification.SupportsOnImportFailure.Should().BeFalse();
|
||||
notification.SupportsOnTrackRetag.Should().BeFalse();
|
||||
notification.SupportsOnApplicationUpdate.Should().BeFalse();
|
||||
notification.SupportsOnManualInteractionRequired.Should().BeFalse();
|
||||
notification.SupportsOnAlbumDelete.Should().BeFalse();
|
||||
notification.SupportsOnArtistDelete.Should().BeFalse();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
using FluentMigrator;
|
||||
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Datastore.Migration
|
||||
{
|
||||
[Migration(067)]
|
||||
public class add_on_manual_interaction_required_to_notifications : NzbDroneMigrationBase
|
||||
{
|
||||
protected override void MainDbUpgrade()
|
||||
{
|
||||
Alter.Table("Notifications").AddColumn("OnManualInteractionRequired").AsBoolean().WithDefaultValue(false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -91,7 +91,8 @@ namespace NzbDrone.Core.Datastore
|
|||
.Ignore(i => i.SupportsOnDownloadFailure)
|
||||
.Ignore(i => i.SupportsOnImportFailure)
|
||||
.Ignore(i => i.SupportsOnTrackRetag)
|
||||
.Ignore(i => i.SupportsOnApplicationUpdate);
|
||||
.Ignore(i => i.SupportsOnApplicationUpdate)
|
||||
.Ignore(i => i.SupportsOnManualInteractionRequired);
|
||||
|
||||
Mapper.Entity<MetadataDefinition>("Metadata").RegisterModel()
|
||||
.Ignore(x => x.ImplementationName)
|
||||
|
|
|
@ -69,7 +69,8 @@ namespace NzbDrone.Core.Download
|
|||
return;
|
||||
}
|
||||
|
||||
var historyItem = _historyService.MostRecentForDownloadId(trackedDownload.DownloadItem.DownloadId);
|
||||
var grabbedHistories = _historyService.FindByDownloadId(trackedDownload.DownloadItem.DownloadId).Where(h => h.EventType == EntityHistoryEventType.Grabbed).ToList();
|
||||
var historyItem = grabbedHistories.MaxBy(h => h.Date);
|
||||
|
||||
if (historyItem == null && trackedDownload.DownloadItem.Category.IsNullOrWhiteSpace())
|
||||
{
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
using NzbDrone.Common.Messaging;
|
||||
using NzbDrone.Core.Download.TrackedDownloads;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.Download
|
||||
{
|
||||
public class ManualInteractionRequiredEvent : IEvent
|
||||
{
|
||||
public RemoteAlbum Album { get; private set; }
|
||||
public TrackedDownload TrackedDownload { get; private set; }
|
||||
public GrabbedReleaseInfo Release { get; private set; }
|
||||
|
||||
public ManualInteractionRequiredEvent(TrackedDownload trackedDownload, GrabbedReleaseInfo release)
|
||||
{
|
||||
TrackedDownload = trackedDownload;
|
||||
Album = trackedDownload.RemoteAlbum;
|
||||
Release = release;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@ namespace NzbDrone.Core.Download.TrackedDownloads
|
|||
IExecute<CheckForFinishedDownloadCommand>,
|
||||
IHandle<AlbumGrabbedEvent>,
|
||||
IHandle<TrackImportedEvent>,
|
||||
IHandle<ManualInteractionRequiredEvent>,
|
||||
IHandle<DownloadsProcessedEvent>,
|
||||
IHandle<TrackedDownloadsRemovedEvent>
|
||||
{
|
||||
|
@ -166,6 +167,11 @@ namespace NzbDrone.Core.Download.TrackedDownloads
|
|||
_refreshDebounce.Execute();
|
||||
}
|
||||
|
||||
public void Handle(ManualInteractionRequiredEvent message)
|
||||
{
|
||||
_refreshDebounce.Execute();
|
||||
}
|
||||
|
||||
public void Handle(TrackImportedEvent message)
|
||||
{
|
||||
_refreshDebounce.Execute();
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
using System;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
|
@ -15,10 +16,11 @@ namespace NzbDrone.Core.Download.TrackedDownloads
|
|||
public DownloadProtocol Protocol { get; set; }
|
||||
public string Indexer { get; set; }
|
||||
public bool IsTrackable { get; set; }
|
||||
public bool HasNotifiedManualInteractionRequired { get; set; }
|
||||
|
||||
public TrackedDownload()
|
||||
{
|
||||
StatusMessages = System.Array.Empty<TrackedDownloadStatusMessage>();
|
||||
StatusMessages = Array.Empty<TrackedDownloadStatusMessage>();
|
||||
}
|
||||
|
||||
public void Warn(string message, params object[] args)
|
||||
|
|
|
@ -108,7 +108,8 @@ namespace NzbDrone.Core.Download.TrackedDownloads
|
|||
DownloadClient = downloadClient.Id,
|
||||
DownloadItem = downloadItem,
|
||||
Protocol = downloadClient.Protocol,
|
||||
IsTrackable = true
|
||||
IsTrackable = true,
|
||||
HasNotifiedManualInteractionRequired = existingItem?.HasNotifiedManualInteractionRequired ?? false
|
||||
};
|
||||
|
||||
try
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
using System.Linq;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.History;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.TrackImport.Aggregation.Aggregators
|
||||
{
|
||||
// public class AggregateReleaseInfo : IAggregateLocalEpisode
|
||||
// {
|
||||
// private readonly IHistoryService _historyService;
|
||||
//
|
||||
// public AggregateReleaseInfo(IHistoryService historyService)
|
||||
// {
|
||||
// _historyService = historyService;
|
||||
// }
|
||||
//
|
||||
// public LocalTrack Aggregate(LocalTrack localTrack, DownloadClientItem downloadClientItem)
|
||||
// {
|
||||
// if (downloadClientItem == null)
|
||||
// {
|
||||
// return localTrack;
|
||||
// }
|
||||
//
|
||||
// var grabbedHistories = _historyService.FindByDownloadId(downloadClientItem.DownloadId)
|
||||
// .Where(h => h.EventType == TrackHistoryEventType.Grabbed)
|
||||
// .ToList();
|
||||
//
|
||||
// if (grabbedHistories.Empty())
|
||||
// {
|
||||
// return localTrack;
|
||||
// }
|
||||
//
|
||||
// localTrack.Release = new GrabbedReleaseInfo(grabbedHistories);
|
||||
//
|
||||
// return localTrack;
|
||||
// }
|
||||
// }
|
||||
}
|
|
@ -62,6 +62,11 @@ namespace NzbDrone.Core.Notifications.Apprise
|
|||
_proxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnManualInteractionRequired(ManualInteractionRequiredMessage message)
|
||||
{
|
||||
_proxy.SendNotification(MANUAL_INTERACTION_REQUIRED_TITLE, message.Message, Settings);
|
||||
}
|
||||
|
||||
public override ValidationResult Test()
|
||||
{
|
||||
var failures = new List<ValidationFailure>();
|
||||
|
|
|
@ -61,6 +61,11 @@ namespace NzbDrone.Core.Notifications.Boxcar
|
|||
_proxy.SendNotification(APPLICATION_UPDATE_TITLE, message.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnManualInteractionRequired(ManualInteractionRequiredMessage message)
|
||||
{
|
||||
_proxy.SendNotification(MANUAL_INTERACTION_REQUIRED_TITLE, message.Message, Settings);
|
||||
}
|
||||
|
||||
public override ValidationResult Test()
|
||||
{
|
||||
var failures = new List<ValidationFailure>();
|
||||
|
|
|
@ -258,6 +258,27 @@ namespace NzbDrone.Core.Notifications.CustomScript
|
|||
ExecuteScript(environmentVariables);
|
||||
}
|
||||
|
||||
public override void OnManualInteractionRequired(ManualInteractionRequiredMessage message)
|
||||
{
|
||||
var artist = message.Artist;
|
||||
var environmentVariables = new StringDictionary();
|
||||
|
||||
environmentVariables.Add("Lidarr_EventType", "ManualInteractionRequired");
|
||||
environmentVariables.Add("Lidarr_InstanceName", _configFileProvider.InstanceName);
|
||||
environmentVariables.Add("Lidarr_ApplicationUrl", _configService.ApplicationUrl);
|
||||
environmentVariables.Add("Lidarr_Artist_Id", artist.Id.ToString());
|
||||
environmentVariables.Add("Lidarr_Artist_Name", artist.Metadata.Value.Name);
|
||||
environmentVariables.Add("Lidarr_Artist_MBId", artist.Metadata.Value.ForeignArtistId);
|
||||
environmentVariables.Add("Lidarr_Artist_Type", artist.Metadata.Value.Type);
|
||||
environmentVariables.Add("Lidarr_Download_Client", message.DownloadClientName ?? string.Empty);
|
||||
environmentVariables.Add("Lidarr_Download_Client_Type", message.DownloadClientType ?? string.Empty);
|
||||
environmentVariables.Add("Lidarr_Download_Id", message.DownloadId ?? string.Empty);
|
||||
environmentVariables.Add("Lidarr_Download_Size", message.TrackedDownload.DownloadItem.TotalSize.ToString());
|
||||
environmentVariables.Add("Lidarr_Download_Title", message.TrackedDownload.DownloadItem.Title);
|
||||
|
||||
ExecuteScript(environmentVariables);
|
||||
}
|
||||
|
||||
public override ValidationResult Test()
|
||||
{
|
||||
var failures = new List<ValidationFailure>();
|
||||
|
|
|
@ -408,6 +408,97 @@ namespace NzbDrone.Core.Notifications.Discord
|
|||
_proxy.SendPayload(payload, Settings);
|
||||
}
|
||||
|
||||
public override void OnManualInteractionRequired(ManualInteractionRequiredMessage message)
|
||||
{
|
||||
var artist = message.Artist;
|
||||
var albums = message.RemoteAlbum.Albums;
|
||||
var artistMetadata = message.Artist.Metadata.Value;
|
||||
|
||||
var embed = new Embed
|
||||
{
|
||||
Author = new DiscordAuthor
|
||||
{
|
||||
Name = Settings.Author.IsNullOrWhiteSpace() ? Environment.MachineName : Settings.Author,
|
||||
IconUrl = "https://raw.githubusercontent.com/Lidarr/Lidarr/develop/Logo/256.png"
|
||||
},
|
||||
Url = $"https://musicbrainz.org/artist/{artist.ForeignArtistId}",
|
||||
Description = "Manual interaction needed",
|
||||
Title = GetTitle(artist, albums),
|
||||
Color = (int)DiscordColors.Standard,
|
||||
Fields = new List<DiscordField>(),
|
||||
Timestamp = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ")
|
||||
};
|
||||
|
||||
if (Settings.ManualInteractionFields.Contains((int)DiscordGrabFieldType.Poster))
|
||||
{
|
||||
embed.Thumbnail = new DiscordImage
|
||||
{
|
||||
Url = albums.First().Images.FirstOrDefault(x => x.CoverType == MediaCoverTypes.Poster)?.Url
|
||||
};
|
||||
}
|
||||
|
||||
if (Settings.ManualInteractionFields.Contains((int)DiscordGrabFieldType.Fanart))
|
||||
{
|
||||
embed.Image = new DiscordImage
|
||||
{
|
||||
Url = artistMetadata.Images.FirstOrDefault(x => x.CoverType == MediaCoverTypes.Fanart)?.Url
|
||||
};
|
||||
}
|
||||
|
||||
foreach (var field in Settings.ManualInteractionFields)
|
||||
{
|
||||
var discordField = new DiscordField();
|
||||
|
||||
switch ((DiscordManualInteractionFieldType)field)
|
||||
{
|
||||
case DiscordManualInteractionFieldType.Overview:
|
||||
var overview = albums.First().Overview ?? "";
|
||||
discordField.Name = "Overview";
|
||||
discordField.Value = overview.Length <= 300 ? overview : $"{overview.AsSpan(0, 300)}...";
|
||||
break;
|
||||
case DiscordManualInteractionFieldType.Rating:
|
||||
discordField.Name = "Rating";
|
||||
discordField.Value = albums.First().Ratings.Value.ToString();
|
||||
break;
|
||||
case DiscordManualInteractionFieldType.Genres:
|
||||
discordField.Name = "Genres";
|
||||
discordField.Value = albums.First().Genres.Take(5).Join(", ");
|
||||
break;
|
||||
case DiscordManualInteractionFieldType.Quality:
|
||||
discordField.Name = "Quality";
|
||||
discordField.Inline = true;
|
||||
discordField.Value = message.Quality.Quality.Name;
|
||||
break;
|
||||
case DiscordManualInteractionFieldType.Group:
|
||||
discordField.Name = "Group";
|
||||
discordField.Value = message.RemoteAlbum.ParsedAlbumInfo.ReleaseGroup;
|
||||
break;
|
||||
case DiscordManualInteractionFieldType.Size:
|
||||
discordField.Name = "Size";
|
||||
discordField.Value = BytesToString(message.RemoteAlbum.Release.Size);
|
||||
discordField.Inline = true;
|
||||
break;
|
||||
case DiscordManualInteractionFieldType.DownloadTitle:
|
||||
discordField.Name = "Download";
|
||||
discordField.Value = string.Format("```{0}```", message.TrackedDownload.DownloadItem.Title);
|
||||
break;
|
||||
case DiscordManualInteractionFieldType.Links:
|
||||
discordField.Name = "Links";
|
||||
discordField.Value = GetLinksString(artist);
|
||||
break;
|
||||
}
|
||||
|
||||
if (discordField.Name.IsNotNullOrWhiteSpace() && discordField.Value.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
embed.Fields.Add(discordField);
|
||||
}
|
||||
}
|
||||
|
||||
var payload = CreatePayload(null, new List<Embed> { embed });
|
||||
|
||||
_proxy.SendPayload(payload, Settings);
|
||||
}
|
||||
|
||||
public override ValidationResult Test()
|
||||
{
|
||||
var failures = new List<ValidationFailure>();
|
||||
|
|
|
@ -28,4 +28,18 @@ namespace NzbDrone.Core.Notifications.Discord
|
|||
Poster,
|
||||
Fanart
|
||||
}
|
||||
|
||||
public enum DiscordManualInteractionFieldType
|
||||
{
|
||||
Overview,
|
||||
Rating,
|
||||
Genres,
|
||||
Quality,
|
||||
Group,
|
||||
Size,
|
||||
Links,
|
||||
DownloadTitle,
|
||||
Poster,
|
||||
Fanart
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,9 @@ namespace NzbDrone.Core.Notifications.Discord
|
|||
public DiscordSettings()
|
||||
{
|
||||
// Set Default Fields
|
||||
GrabFields = new int[] { 0, 1, 2, 3, 5, 6, 7, 8, 9 };
|
||||
ImportFields = new int[] { 0, 1, 2, 3, 5, 6, 7, 8, 9 };
|
||||
GrabFields = new[] { 0, 1, 2, 3, 5, 6, 7, 8, 9 };
|
||||
ImportFields = new[] { 0, 1, 2, 3, 5, 6, 7, 8, 9 };
|
||||
ManualInteractionFields = new[] { 0, 1, 2, 3, 5, 6, 7, 8, 9 };
|
||||
}
|
||||
|
||||
private static readonly DiscordSettingsValidator Validator = new DiscordSettingsValidator();
|
||||
|
@ -43,6 +44,9 @@ namespace NzbDrone.Core.Notifications.Discord
|
|||
[FieldDefinition(5, Label = "On Import Fields", Advanced = true, SelectOptions = typeof(DiscordImportFieldType), HelpText = "Change the fields that are passed for this 'on import' notification", Type = FieldType.TagSelect)]
|
||||
public IEnumerable<int> ImportFields { get; set; }
|
||||
|
||||
[FieldDefinition(6, Label = "On Manual Interaction Fields", Advanced = true, SelectOptions = typeof(DiscordManualInteractionFieldType), HelpText = "Change the fields that are passed for this 'on manual interaction' notification", Type = FieldType.TagSelect)]
|
||||
public IEnumerable<int> ManualInteractionFields { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
|
|
|
@ -82,6 +82,13 @@ namespace NzbDrone.Core.Notifications.Email
|
|||
SendEmail(Settings, APPLICATION_UPDATE_TITLE_BRANDED, body);
|
||||
}
|
||||
|
||||
public override void OnManualInteractionRequired(ManualInteractionRequiredMessage message)
|
||||
{
|
||||
var body = $"{message.Message} requires manual interaction.";
|
||||
|
||||
SendEmail(Settings, MANUAL_INTERACTION_REQUIRED_TITLE_BRANDED, body);
|
||||
}
|
||||
|
||||
public override ValidationResult Test()
|
||||
{
|
||||
var failures = new List<ValidationFailure>();
|
||||
|
|
|
@ -68,6 +68,11 @@ namespace NzbDrone.Core.Notifications.Gotify
|
|||
SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, null);
|
||||
}
|
||||
|
||||
public override void OnManualInteractionRequired(ManualInteractionRequiredMessage message)
|
||||
{
|
||||
SendNotification(MANUAL_INTERACTION_REQUIRED_TITLE, message.Message, message.Artist);
|
||||
}
|
||||
|
||||
public override ValidationResult Test()
|
||||
{
|
||||
var failures = new List<ValidationFailure>();
|
||||
|
|
|
@ -17,6 +17,7 @@ namespace NzbDrone.Core.Notifications
|
|||
void OnHealthIssue(HealthCheck.HealthCheck healthCheck);
|
||||
void OnHealthRestored(HealthCheck.HealthCheck previousCheck);
|
||||
void OnApplicationUpdate(ApplicationUpdateMessage updateMessage);
|
||||
void OnManualInteractionRequired(ManualInteractionRequiredMessage message);
|
||||
void OnDownloadFailure(DownloadFailedMessage message);
|
||||
void OnImportFailure(AlbumDownloadMessage message);
|
||||
void OnTrackRetag(TrackRetagMessage message);
|
||||
|
@ -30,6 +31,7 @@ namespace NzbDrone.Core.Notifications
|
|||
bool SupportsOnHealthIssue { get; }
|
||||
bool SupportsOnHealthRestored { get; }
|
||||
bool SupportsOnApplicationUpdate { get; }
|
||||
bool SupportsOnManualInteractionRequired { get; }
|
||||
bool SupportsOnDownloadFailure { get; }
|
||||
bool SupportsOnImportFailure { get; }
|
||||
bool SupportsOnTrackRetag { get; }
|
||||
|
|
|
@ -52,6 +52,11 @@ namespace NzbDrone.Core.Notifications.Join
|
|||
_proxy.SendNotification(APPLICATION_UPDATE_TITLE_BRANDED, updateMessage.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnManualInteractionRequired(ManualInteractionRequiredMessage message)
|
||||
{
|
||||
_proxy.SendNotification(MANUAL_INTERACTION_REQUIRED_TITLE_BRANDED, message.Message, Settings);
|
||||
}
|
||||
|
||||
public override ValidationResult Test()
|
||||
{
|
||||
var failures = new List<ValidationFailure>();
|
||||
|
|
|
@ -54,6 +54,11 @@ namespace NzbDrone.Core.Notifications.Mailgun
|
|||
_proxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnManualInteractionRequired(ManualInteractionRequiredMessage message)
|
||||
{
|
||||
_proxy.SendNotification(MANUAL_INTERACTION_REQUIRED_TITLE, message.Message, Settings);
|
||||
}
|
||||
|
||||
public override ValidationResult Test()
|
||||
{
|
||||
var failures = new List<ValidationFailure>();
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
using NzbDrone.Core.Download.TrackedDownloads;
|
||||
using NzbDrone.Core.Music;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Qualities;
|
||||
|
||||
namespace NzbDrone.Core.Notifications
|
||||
{
|
||||
public class ManualInteractionRequiredMessage
|
||||
{
|
||||
public string Message { get; set; }
|
||||
public Artist Artist { get; set; }
|
||||
public RemoteAlbum RemoteAlbum { get; set; }
|
||||
public TrackedDownload TrackedDownload { get; set; }
|
||||
public QualityModel Quality { get; set; }
|
||||
public string DownloadClientType { get; set; }
|
||||
public string DownloadClientName { get; set; }
|
||||
public string DownloadId { get; set; }
|
||||
public GrabbedReleaseInfo Release { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Message;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -77,6 +77,11 @@ namespace NzbDrone.Core.Notifications.Notifiarr
|
|||
_proxy.SendNotification(BuildApplicationUpdatePayload(updateMessage), Settings);
|
||||
}
|
||||
|
||||
public override void OnManualInteractionRequired(ManualInteractionRequiredMessage message)
|
||||
{
|
||||
_proxy.SendNotification(BuildManualInteractionRequiredPayload(message), Settings);
|
||||
}
|
||||
|
||||
public override ValidationResult Test()
|
||||
{
|
||||
var failures = new List<ValidationFailure>();
|
||||
|
|
|
@ -20,6 +20,7 @@ namespace NzbDrone.Core.Notifications
|
|||
protected const string IMPORT_FAILURE_TITLE = "Import Failed";
|
||||
protected const string TRACK_RETAGGED_TITLE = "Track File Tags Updated";
|
||||
protected const string APPLICATION_UPDATE_TITLE = "Application Updated";
|
||||
protected const string MANUAL_INTERACTION_REQUIRED_TITLE = "Manual Interaction";
|
||||
|
||||
protected const string ALBUM_GRABBED_TITLE_BRANDED = "Lidarr - " + ALBUM_GRABBED_TITLE;
|
||||
protected const string ALBUM_DOWNLOADED_TITLE_BRANDED = "Lidarr - " + ALBUM_DOWNLOADED_TITLE;
|
||||
|
@ -31,6 +32,7 @@ namespace NzbDrone.Core.Notifications
|
|||
protected const string IMPORT_FAILURE_TITLE_BRANDED = "Lidarr - " + IMPORT_FAILURE_TITLE;
|
||||
protected const string TRACK_RETAGGED_TITLE_BRANDED = "Lidarr - " + TRACK_RETAGGED_TITLE;
|
||||
protected const string APPLICATION_UPDATE_TITLE_BRANDED = "Lidarr - " + APPLICATION_UPDATE_TITLE;
|
||||
protected const string MANUAL_INTERACTION_REQUIRED_TITLE_BRANDED = "Lidarr - " + MANUAL_INTERACTION_REQUIRED_TITLE;
|
||||
|
||||
public abstract string Name { get; }
|
||||
|
||||
|
@ -89,6 +91,10 @@ namespace NzbDrone.Core.Notifications
|
|||
{
|
||||
}
|
||||
|
||||
public virtual void OnManualInteractionRequired(ManualInteractionRequiredMessage message)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void ProcessQueue()
|
||||
{
|
||||
}
|
||||
|
@ -105,6 +111,7 @@ namespace NzbDrone.Core.Notifications
|
|||
public bool SupportsOnImportFailure => HasConcreteImplementation("OnImportFailure");
|
||||
public bool SupportsOnTrackRetag => HasConcreteImplementation("OnTrackRetag");
|
||||
public bool SupportsOnApplicationUpdate => HasConcreteImplementation("OnApplicationUpdate");
|
||||
public bool SupportsOnManualInteractionRequired => HasConcreteImplementation("OnManualInteractionRequired");
|
||||
|
||||
protected TSettings Settings => (TSettings)Definition.Settings;
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace NzbDrone.Core.Notifications
|
|||
public bool OnImportFailure { get; set; }
|
||||
public bool OnTrackRetag { get; set; }
|
||||
public bool OnApplicationUpdate { get; set; }
|
||||
public bool OnManualInteractionRequired { get; set; }
|
||||
public bool SupportsOnGrab { get; set; }
|
||||
public bool SupportsOnReleaseImport { get; set; }
|
||||
public bool SupportsOnUpgrade { get; set; }
|
||||
|
@ -29,7 +30,8 @@ namespace NzbDrone.Core.Notifications
|
|||
public bool SupportsOnImportFailure { get; set; }
|
||||
public bool SupportsOnTrackRetag { get; set; }
|
||||
public bool SupportsOnApplicationUpdate { get; set; }
|
||||
public bool SupportsOnManualInteractionRequired { get; set; }
|
||||
|
||||
public override bool Enable => OnGrab || OnReleaseImport || (OnReleaseImport && OnUpgrade) || OnAlbumDelete || OnArtistDelete || OnHealthIssue || OnHealthRestored || OnDownloadFailure || OnImportFailure || OnTrackRetag || OnApplicationUpdate;
|
||||
public override bool Enable => OnGrab || OnReleaseImport || (OnReleaseImport && OnUpgrade) || OnAlbumDelete || OnArtistDelete || OnHealthIssue || OnHealthRestored || OnDownloadFailure || OnImportFailure || OnTrackRetag || OnApplicationUpdate || OnManualInteractionRequired;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ namespace NzbDrone.Core.Notifications
|
|||
List<INotification> OnImportFailureEnabled();
|
||||
List<INotification> OnTrackRetagEnabled();
|
||||
List<INotification> OnApplicationUpdateEnabled();
|
||||
List<INotification> OnManualInteractionEnabled();
|
||||
}
|
||||
|
||||
public class NotificationFactory : ProviderFactory<INotification, NotificationDefinition>, INotificationFactory
|
||||
|
@ -91,6 +92,11 @@ namespace NzbDrone.Core.Notifications
|
|||
return GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnApplicationUpdate).ToList();
|
||||
}
|
||||
|
||||
public List<INotification> OnManualInteractionEnabled()
|
||||
{
|
||||
return GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnManualInteractionRequired).ToList();
|
||||
}
|
||||
|
||||
public override void SetProviderCharacteristics(INotification provider, NotificationDefinition definition)
|
||||
{
|
||||
base.SetProviderCharacteristics(provider, definition);
|
||||
|
@ -107,6 +113,7 @@ namespace NzbDrone.Core.Notifications
|
|||
definition.SupportsOnImportFailure = provider.SupportsOnImportFailure;
|
||||
definition.SupportsOnTrackRetag = provider.SupportsOnTrackRetag;
|
||||
definition.SupportsOnApplicationUpdate = provider.SupportsOnApplicationUpdate;
|
||||
definition.SupportsOnManualInteractionRequired = provider.SupportsOnManualInteractionRequired;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ using System.Linq;
|
|||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Download.TrackedDownloads;
|
||||
using NzbDrone.Core.HealthCheck;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
|
@ -28,6 +29,7 @@ namespace NzbDrone.Core.Notifications
|
|||
IHandle<AlbumImportIncompleteEvent>,
|
||||
IHandle<TrackFileRetaggedEvent>,
|
||||
IHandle<UpdateInstalledEvent>,
|
||||
IHandle<ManualInteractionRequiredEvent>,
|
||||
IHandleAsync<RenameCompletedEvent>,
|
||||
IHandleAsync<DeleteCompletedEvent>,
|
||||
IHandleAsync<HealthCheckCompleteEvent>
|
||||
|
@ -376,6 +378,39 @@ namespace NzbDrone.Core.Notifications
|
|||
}
|
||||
}
|
||||
|
||||
public void Handle(ManualInteractionRequiredEvent message)
|
||||
{
|
||||
var manualInteractionMessage = new ManualInteractionRequiredMessage
|
||||
{
|
||||
Message = GetMessage(message.Album.Artist, message.Album.Albums, message.Album.ParsedAlbumInfo.Quality),
|
||||
Artist = message.Album.Artist,
|
||||
Quality = message.Album.ParsedAlbumInfo.Quality,
|
||||
RemoteAlbum = message.Album,
|
||||
TrackedDownload = message.TrackedDownload,
|
||||
DownloadClientType = message.TrackedDownload.DownloadItem.DownloadClientInfo.Type,
|
||||
DownloadClientName = message.TrackedDownload.DownloadItem.DownloadClientInfo.Name,
|
||||
DownloadId = message.TrackedDownload.DownloadItem.DownloadId,
|
||||
Release = message.Release
|
||||
};
|
||||
|
||||
foreach (var notification in _notificationFactory.OnManualInteractionEnabled())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!ShouldHandleArtist(notification.Definition, message.Album.Artist))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
notification.OnManualInteractionRequired(manualInteractionMessage);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "Unable to send OnManualInteractionRequired notification to {0}", notification.Definition.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void HandleAsync(RenameCompletedEvent message)
|
||||
{
|
||||
ProcessQueue();
|
||||
|
|
|
@ -63,6 +63,11 @@ namespace NzbDrone.Core.Notifications.Ntfy
|
|||
_proxy.SendNotification(APPLICATION_UPDATE_TITLE_BRANDED, updateMessage.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnManualInteractionRequired(ManualInteractionRequiredMessage message)
|
||||
{
|
||||
_proxy.SendNotification(MANUAL_INTERACTION_REQUIRED_TITLE_BRANDED, message.Message, Settings);
|
||||
}
|
||||
|
||||
public override ValidationResult Test()
|
||||
{
|
||||
var failures = new List<ValidationFailure>();
|
||||
|
|
|
@ -51,6 +51,11 @@ namespace NzbDrone.Core.Notifications.Prowl
|
|||
_prowlProxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnManualInteractionRequired(ManualInteractionRequiredMessage message)
|
||||
{
|
||||
_prowlProxy.SendNotification(MANUAL_INTERACTION_REQUIRED_TITLE, message.Message, Settings);
|
||||
}
|
||||
|
||||
public override ValidationResult Test()
|
||||
{
|
||||
var failures = new List<ValidationFailure>();
|
||||
|
|
|
@ -64,6 +64,11 @@ namespace NzbDrone.Core.Notifications.PushBullet
|
|||
_proxy.SendNotification(APPLICATION_UPDATE_TITLE_BRANDED, updateMessage.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnManualInteractionRequired(ManualInteractionRequiredMessage message)
|
||||
{
|
||||
_proxy.SendNotification(MANUAL_INTERACTION_REQUIRED_TITLE_BRANDED, message.Message, Settings);
|
||||
}
|
||||
|
||||
public override ValidationResult Test()
|
||||
{
|
||||
var failures = new List<ValidationFailure>();
|
||||
|
|
|
@ -61,6 +61,11 @@ namespace NzbDrone.Core.Notifications.Pushover
|
|||
_proxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnManualInteractionRequired(ManualInteractionRequiredMessage message)
|
||||
{
|
||||
_proxy.SendNotification(MANUAL_INTERACTION_REQUIRED_TITLE, message.Message, Settings);
|
||||
}
|
||||
|
||||
public override ValidationResult Test()
|
||||
{
|
||||
var failures = new List<ValidationFailure>();
|
||||
|
|
|
@ -64,6 +64,11 @@ namespace NzbDrone.Core.Notifications.SendGrid
|
|||
_proxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnManualInteractionRequired(ManualInteractionRequiredMessage message)
|
||||
{
|
||||
_proxy.SendNotification(MANUAL_INTERACTION_REQUIRED_TITLE, message.Message, Settings);
|
||||
}
|
||||
|
||||
public override ValidationResult Test()
|
||||
{
|
||||
var failures = new List<ValidationFailure>();
|
||||
|
|
|
@ -61,6 +61,11 @@ namespace NzbDrone.Core.Notifications.Simplepush
|
|||
_proxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnManualInteractionRequired(ManualInteractionRequiredMessage message)
|
||||
{
|
||||
_proxy.SendNotification(MANUAL_INTERACTION_REQUIRED_TITLE, message.Message, Settings);
|
||||
}
|
||||
|
||||
public override ValidationResult Test()
|
||||
{
|
||||
var failures = new List<ValidationFailure>();
|
||||
|
|
|
@ -202,6 +202,23 @@ namespace NzbDrone.Core.Notifications.Slack
|
|||
_proxy.SendPayload(payload, Settings);
|
||||
}
|
||||
|
||||
public override void OnManualInteractionRequired(ManualInteractionRequiredMessage message)
|
||||
{
|
||||
var attachments = new List<Attachment>
|
||||
{
|
||||
new Attachment
|
||||
{
|
||||
Title = Environment.MachineName,
|
||||
Text = message.Message,
|
||||
Color = "warning"
|
||||
}
|
||||
};
|
||||
|
||||
var payload = CreatePayload("Manual Interaction Required", attachments);
|
||||
|
||||
_proxy.SendPayload(payload, Settings);
|
||||
}
|
||||
|
||||
public override ValidationResult Test()
|
||||
{
|
||||
var failures = new List<ValidationFailure>();
|
||||
|
|
|
@ -61,6 +61,11 @@ namespace NzbDrone.Core.Notifications.Telegram
|
|||
_proxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings);
|
||||
}
|
||||
|
||||
public override void OnManualInteractionRequired(ManualInteractionRequiredMessage message)
|
||||
{
|
||||
_proxy.SendNotification(MANUAL_INTERACTION_REQUIRED_TITLE, message.Message, Settings);
|
||||
}
|
||||
|
||||
public override ValidationResult Test()
|
||||
{
|
||||
var failures = new List<ValidationFailure>();
|
||||
|
|
|
@ -63,6 +63,11 @@ namespace NzbDrone.Core.Notifications.Twitter
|
|||
_twitterService.SendNotification($"Application Updated: {updateMessage.Message}", Settings);
|
||||
}
|
||||
|
||||
public override void OnManualInteractionRequired(ManualInteractionRequiredMessage message)
|
||||
{
|
||||
_twitterService.SendNotification($"Manual Interaction Required: {message.Message}", Settings);
|
||||
}
|
||||
|
||||
public override object RequestAction(string action, IDictionary<string, string> query)
|
||||
{
|
||||
if (action == "startOAuth")
|
||||
|
|
|
@ -75,6 +75,11 @@ namespace NzbDrone.Core.Notifications.Webhook
|
|||
_proxy.SendWebhook(BuildApplicationUpdatePayload(updateMessage), Settings);
|
||||
}
|
||||
|
||||
public override void OnManualInteractionRequired(ManualInteractionRequiredMessage message)
|
||||
{
|
||||
_proxy.SendWebhook(BuildManualInteractionRequiredPayload(message), Settings);
|
||||
}
|
||||
|
||||
public override string Name => "Webhook";
|
||||
|
||||
public override ValidationResult Test()
|
||||
|
|
|
@ -194,6 +194,28 @@ namespace NzbDrone.Core.Notifications.Webhook
|
|||
};
|
||||
}
|
||||
|
||||
protected WebhookManualInteractionPayload BuildManualInteractionRequiredPayload(ManualInteractionRequiredMessage message)
|
||||
{
|
||||
var remoteAlbum = message.RemoteAlbum;
|
||||
var quality = message.Quality;
|
||||
|
||||
return new WebhookManualInteractionPayload
|
||||
{
|
||||
EventType = WebhookEventType.ManualInteractionRequired,
|
||||
InstanceName = _configFileProvider.InstanceName,
|
||||
ApplicationUrl = _configService.ApplicationUrl,
|
||||
Artist = new WebhookArtist(message.Artist),
|
||||
Albums = remoteAlbum.Albums.Select(x => new WebhookAlbum(x)).ToList(),
|
||||
DownloadInfo = new WebhookDownloadClientItem(quality, message.TrackedDownload.DownloadItem),
|
||||
DownloadClient = message.DownloadClientName,
|
||||
DownloadClientType = message.DownloadClientType,
|
||||
DownloadId = message.DownloadId,
|
||||
|
||||
// CustomFormatInfo = new WebhookCustomFormatInfo(remoteAlbum.CustomFormats, remoteAlbum.CustomFormatScore),
|
||||
// Release = new WebhookGrabbedRelease(message.Release)
|
||||
};
|
||||
}
|
||||
|
||||
protected WebhookPayload BuildTestPayload()
|
||||
{
|
||||
return new WebhookGrabPayload
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Qualities;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Webhook
|
||||
{
|
||||
public class WebhookDownloadClientItem
|
||||
{
|
||||
public WebhookDownloadClientItem()
|
||||
{
|
||||
}
|
||||
|
||||
public WebhookDownloadClientItem(QualityModel quality, DownloadClientItem downloadClientItem)
|
||||
{
|
||||
Quality = quality.Quality.Name;
|
||||
QualityVersion = quality.Revision.Version;
|
||||
Title = downloadClientItem.Title;
|
||||
Size = downloadClientItem.TotalSize;
|
||||
}
|
||||
|
||||
public string Quality { get; set; }
|
||||
public int QualityVersion { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string Indexer { get; set; }
|
||||
public long Size { get; set; }
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@ namespace NzbDrone.Core.Notifications.Webhook
|
|||
Health,
|
||||
Retag,
|
||||
ApplicationUpdate,
|
||||
HealthRestored
|
||||
HealthRestored,
|
||||
ManualInteractionRequired
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace NzbDrone.Core.Notifications.Webhook
|
||||
{
|
||||
public class WebhookManualInteractionPayload : WebhookPayload
|
||||
{
|
||||
public WebhookArtist Artist { get; set; }
|
||||
public List<WebhookAlbum> Albums { get; set; }
|
||||
public WebhookDownloadClientItem DownloadInfo { get; set; }
|
||||
public string DownloadClient { get; set; }
|
||||
public string DownloadClientType { get; set; }
|
||||
public string DownloadId { get; set; }
|
||||
|
||||
// public WebhookCustomFormatInfo CustomFormatInfo { get; set; }
|
||||
// public WebhookGrabbedRelease Release { get; set; }
|
||||
}
|
||||
}
|
|
@ -62,6 +62,11 @@ namespace NzbDrone.Core.Notifications.Xbmc
|
|||
Notify(Settings, APPLICATION_UPDATE_TITLE_BRANDED, updateMessage.Message);
|
||||
}
|
||||
|
||||
public override void OnManualInteractionRequired(ManualInteractionRequiredMessage message)
|
||||
{
|
||||
Notify(Settings, MANUAL_INTERACTION_REQUIRED_TITLE, message.Message);
|
||||
}
|
||||
|
||||
public override string Name => "Kodi";
|
||||
|
||||
public override ValidationResult Test()
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Core.History;
|
||||
|
||||
namespace NzbDrone.Core.Parser.Model
|
||||
{
|
||||
public class GrabbedReleaseInfo
|
||||
{
|
||||
public string Title { get; set; }
|
||||
public string Indexer { get; set; }
|
||||
public long Size { get; set; }
|
||||
|
||||
public List<int> AlbumsIds { get; set; }
|
||||
|
||||
public GrabbedReleaseInfo(List<EntityHistory> grabbedHistories)
|
||||
{
|
||||
var grabbedHistory = grabbedHistories.MaxBy(h => h.Date);
|
||||
var albumsIds = grabbedHistories.Select(h => h.AlbumId).Distinct().ToList();
|
||||
|
||||
grabbedHistory.Data.TryGetValue("indexer", out var indexer);
|
||||
grabbedHistory.Data.TryGetValue("size", out var sizeString);
|
||||
long.TryParse(sizeString, out var size);
|
||||
|
||||
Title = grabbedHistory.SourceTitle;
|
||||
Indexer = indexer;
|
||||
Size = size;
|
||||
AlbumsIds = albumsIds;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue