1
0
mirror of https://github.com/Sonarr/Sonarr.git synced 2024-11-24 19:52:39 +01:00

New: OnApplicationUpdate Notifications

Closes #4810
Co-authored-by: Qstick <qstick@gmail.com>
This commit is contained in:
bakerboy448 2022-01-23 15:24:34 -06:00 committed by GitHub
parent cee17483d9
commit 71dba904a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 501 additions and 194 deletions

View File

@ -1,10 +1,10 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { sizes } from 'Helpers/Props';
import Button from 'Components/Link/Button'; import Button from 'Components/Link/Button';
import Link from 'Components/Link/Link'; import Link from 'Components/Link/Link';
import Menu from 'Components/Menu/Menu'; import Menu from 'Components/Menu/Menu';
import MenuContent from 'Components/Menu/MenuContent'; import MenuContent from 'Components/Menu/MenuContent';
import { sizes } from 'Helpers/Props';
import AddNotificationPresetMenuItem from './AddNotificationPresetMenuItem'; import AddNotificationPresetMenuItem from './AddNotificationPresetMenuItem';
import styles from './AddNotificationItem.css'; import styles from './AddNotificationItem.css';
@ -90,7 +90,7 @@ class AddNotificationItem extends Component {
to={infoLink} to={infoLink}
size={sizes.SMALL} size={sizes.SMALL}
> >
More info More Info
</Button> </Button>
</div> </div>
</div> </div>

View File

@ -9,12 +9,3 @@
margin-bottom: 30px; margin-bottom: 30px;
} }
.triggers {
margin-top: 3px;
}
.triggerEvents {
margin-top: 10px;
user-select: none;
}

View File

@ -1,20 +1,20 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import { inputTypes, kinds } from 'Helpers/Props';
import Alert from 'Components/Alert'; import Alert from 'Components/Alert';
import Form from 'Components/Form/Form';
import FormGroup from 'Components/Form/FormGroup';
import FormInputGroup from 'Components/Form/FormInputGroup';
import FormLabel from 'Components/Form/FormLabel';
import ProviderFieldFormGroup from 'Components/Form/ProviderFieldFormGroup';
import Button from 'Components/Link/Button'; import Button from 'Components/Link/Button';
import SpinnerErrorButton from 'Components/Link/SpinnerErrorButton'; import SpinnerErrorButton from 'Components/Link/SpinnerErrorButton';
import LoadingIndicator from 'Components/Loading/LoadingIndicator'; import LoadingIndicator from 'Components/Loading/LoadingIndicator';
import ModalContent from 'Components/Modal/ModalContent';
import ModalHeader from 'Components/Modal/ModalHeader';
import ModalBody from 'Components/Modal/ModalBody'; import ModalBody from 'Components/Modal/ModalBody';
import ModalContent from 'Components/Modal/ModalContent';
import ModalFooter from 'Components/Modal/ModalFooter'; import ModalFooter from 'Components/Modal/ModalFooter';
import Form from 'Components/Form/Form'; import ModalHeader from 'Components/Modal/ModalHeader';
import FormGroup from 'Components/Form/FormGroup'; import { inputTypes, kinds } from 'Helpers/Props';
import FormLabel from 'Components/Form/FormLabel'; import NotificationEventItems from './NotificationEventItems';
import FormInputGroup from 'Components/Form/FormInputGroup';
import FormInputHelpText from 'Components/Form/FormInputHelpText';
import ProviderFieldFormGroup from 'Components/Form/ProviderFieldFormGroup';
import styles from './EditNotificationModalContent.css'; import styles from './EditNotificationModalContent.css';
function EditNotificationModalContent(props) { function EditNotificationModalContent(props) {
@ -39,23 +39,6 @@ function EditNotificationModalContent(props) {
id, id,
implementationName, implementationName,
name, name,
onGrab,
onDownload,
onUpgrade,
onRename,
onSeriesDelete,
onEpisodeFileDelete,
onEpisodeFileDeleteForUpgrade,
onHealthIssue,
supportsOnGrab,
supportsOnDownload,
supportsOnUpgrade,
supportsOnRename,
supportsOnSeriesDelete,
supportsOnEpisodeFileDelete,
supportsOnEpisodeFileDeleteForUpgrade,
supportsOnHealthIssue,
includeHealthWarnings,
tags, tags,
fields, fields,
message message
@ -75,7 +58,9 @@ function EditNotificationModalContent(props) {
{ {
!isFetching && !!error && !isFetching && !!error &&
<div>Unable to add a new notification, please try again.</div> <div>
Unable to add a new notification, please try again.
</div>
} }
{ {
@ -102,111 +87,10 @@ function EditNotificationModalContent(props) {
/> />
</FormGroup> </FormGroup>
<FormGroup> <NotificationEventItems
<FormLabel>Triggers</FormLabel> item={item}
onInputChange={onInputChange}
<div className={styles.triggers}> />
<FormInputHelpText
text="Select which events should trigger this conection"
link="https://wiki.servarr.com/sonarr/settings#connections"
/>
<div className={styles.triggerEvents}>
<FormInputGroup
type={inputTypes.CHECK}
name="onGrab"
helpText="On Grab"
isDisabled={!supportsOnGrab.value}
{...onGrab}
onChange={onInputChange}
/>
<FormInputGroup
type={inputTypes.CHECK}
name="onDownload"
helpText="On Import"
isDisabled={!supportsOnDownload.value}
{...onDownload}
onChange={onInputChange}
/>
{
onDownload.value ?
<FormInputGroup
type={inputTypes.CHECK}
name="onUpgrade"
helpText="On Upgrade"
isDisabled={!supportsOnUpgrade.value}
{...onUpgrade}
onChange={onInputChange}
/> :
null
}
<FormInputGroup
type={inputTypes.CHECK}
name="onRename"
helpText="On Rename"
isDisabled={!supportsOnRename.value}
{...onRename}
onChange={onInputChange}
/>
<FormInputGroup
type={inputTypes.CHECK}
name="onSeriesDelete"
helpText="On Series Delete"
isDisabled={!supportsOnSeriesDelete.value}
{...onSeriesDelete}
onChange={onInputChange}
/>
<FormInputGroup
type={inputTypes.CHECK}
name="onEpisodeFileDelete"
helpText="On Episode File Delete"
isDisabled={!supportsOnEpisodeFileDelete.value}
{...onEpisodeFileDelete}
onChange={onInputChange}
/>
{
onEpisodeFileDelete.value ?
<FormInputGroup
type={inputTypes.CHECK}
name="onEpisodeFileDeleteForUpgrade"
helpText="On Episode File Delete For Upgrade"
isDisabled={!supportsOnEpisodeFileDeleteForUpgrade.value}
{...onEpisodeFileDeleteForUpgrade}
onChange={onInputChange}
/> :
null
}
<FormInputGroup
type={inputTypes.CHECK}
name="onHealthIssue"
helpText="On Health Issue"
isDisabled={!supportsOnHealthIssue.value}
{...onHealthIssue}
onChange={onInputChange}
/>
{
onHealthIssue.value ?
<FormInputGroup
type={inputTypes.CHECK}
name="includeHealthWarnings"
helpText="Include Health Warnings"
isDisabled={!supportsOnHealthIssue.value}
{...includeHealthWarnings}
onChange={onInputChange}
/> :
null
}
</div>
</div>
</FormGroup>
<FormGroup> <FormGroup>
<FormLabel>Tags</FormLabel> <FormLabel>Tags</FormLabel>

View File

@ -2,8 +2,8 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import { saveNotification, setNotificationFieldValue, setNotificationValue, testNotification } from 'Store/Actions/settingsActions';
import createProviderSettingsSelector from 'Store/Selectors/createProviderSettingsSelector'; import createProviderSettingsSelector from 'Store/Selectors/createProviderSettingsSelector';
import { setNotificationValue, setNotificationFieldValue, saveNotification, testNotification } from 'Store/Actions/settingsActions';
import EditNotificationModalContent from './EditNotificationModalContent'; import EditNotificationModalContent from './EditNotificationModalContent';
function createMapStateToProps() { function createMapStateToProps() {

View File

@ -1,9 +1,9 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { kinds } from 'Helpers/Props';
import Card from 'Components/Card'; import Card from 'Components/Card';
import Label from 'Components/Label'; import Label from 'Components/Label';
import ConfirmModal from 'Components/Modal/ConfirmModal'; import ConfirmModal from 'Components/Modal/ConfirmModal';
import { kinds } from 'Helpers/Props';
import EditNotificationModalConnector from './EditNotificationModalConnector'; import EditNotificationModalConnector from './EditNotificationModalConnector';
import styles from './Notification.css'; import styles from './Notification.css';
@ -39,7 +39,7 @@ class Notification extends Component {
}); });
} }
onDeleteNotificationModalClose= () => { onDeleteNotificationModalClose = () => {
this.setState({ isDeleteNotificationModalOpen: false }); this.setState({ isDeleteNotificationModalOpen: false });
} }
@ -62,6 +62,7 @@ class Notification extends Component {
onEpisodeFileDelete, onEpisodeFileDelete,
onEpisodeFileDeleteForUpgrade, onEpisodeFileDeleteForUpgrade,
onHealthIssue, onHealthIssue,
onApplicationUpdate,
supportsOnGrab, supportsOnGrab,
supportsOnDownload, supportsOnDownload,
supportsOnUpgrade, supportsOnUpgrade,
@ -69,7 +70,8 @@ class Notification extends Component {
supportsOnSeriesDelete, supportsOnSeriesDelete,
supportsOnEpisodeFileDelete, supportsOnEpisodeFileDelete,
supportsOnEpisodeFileDeleteForUpgrade, supportsOnEpisodeFileDeleteForUpgrade,
supportsOnHealthIssue supportsOnHealthIssue,
supportsOnApplicationUpdate
} = this.props; } = this.props;
return ( return (
@ -122,6 +124,14 @@ class Notification extends Component {
null null
} }
{
supportsOnApplicationUpdate && onApplicationUpdate ?
<Label kind={kinds.SUCCESS}>
On Application Update
</Label> :
null
}
{ {
supportsOnSeriesDelete && onSeriesDelete ? supportsOnSeriesDelete && onSeriesDelete ?
<Label kind={kinds.SUCCESS}> <Label kind={kinds.SUCCESS}>
@ -147,7 +157,7 @@ class Notification extends Component {
} }
{ {
!onGrab && !onDownload && !onRename && !onHealthIssue && !onSeriesDelete && !onEpisodeFileDelete ? !onGrab && !onDownload && !onRename && !onHealthIssue && !onApplicationUpdate && !onSeriesDelete && !onEpisodeFileDelete ?
<Label <Label
kind={kinds.DISABLED} kind={kinds.DISABLED}
outline={true} outline={true}
@ -189,6 +199,7 @@ Notification.propTypes = {
onEpisodeFileDelete: PropTypes.bool.isRequired, onEpisodeFileDelete: PropTypes.bool.isRequired,
onEpisodeFileDeleteForUpgrade: PropTypes.bool.isRequired, onEpisodeFileDeleteForUpgrade: PropTypes.bool.isRequired,
onHealthIssue: PropTypes.bool.isRequired, onHealthIssue: PropTypes.bool.isRequired,
onApplicationUpdate: PropTypes.bool.isRequired,
supportsOnGrab: PropTypes.bool.isRequired, supportsOnGrab: PropTypes.bool.isRequired,
supportsOnDownload: PropTypes.bool.isRequired, supportsOnDownload: PropTypes.bool.isRequired,
supportsOnSeriesDelete: PropTypes.bool.isRequired, supportsOnSeriesDelete: PropTypes.bool.isRequired,
@ -197,6 +208,7 @@ Notification.propTypes = {
supportsOnUpgrade: PropTypes.bool.isRequired, supportsOnUpgrade: PropTypes.bool.isRequired,
supportsOnRename: PropTypes.bool.isRequired, supportsOnRename: PropTypes.bool.isRequired,
supportsOnHealthIssue: PropTypes.bool.isRequired, supportsOnHealthIssue: PropTypes.bool.isRequired,
supportsOnApplicationUpdate: PropTypes.bool.isRequired,
onConfirmDeleteNotification: PropTypes.func.isRequired onConfirmDeleteNotification: PropTypes.func.isRequired
}; };

View File

@ -0,0 +1,4 @@
.events {
margin-top: 10px;
user-select: none;
}

View File

@ -0,0 +1,176 @@
import PropTypes from 'prop-types';
import React from 'react';
import FormGroup from 'Components/Form/FormGroup';
import FormInputGroup from 'Components/Form/FormInputGroup';
import FormInputHelpText from 'Components/Form/FormInputHelpText';
import FormLabel from 'Components/Form/FormLabel';
import { inputTypes } from 'Helpers/Props';
import styles from './NotificationEventItems.css';
function NotificationEventItems(props) {
const {
item,
onInputChange
} = props;
const {
onGrab,
onDownload,
onUpgrade,
onRename,
onSeriesDelete,
onEpisodeFileDelete,
onEpisodeFileDeleteForUpgrade,
onHealthIssue,
onApplicationUpdate,
supportsOnGrab,
supportsOnDownload,
supportsOnUpgrade,
supportsOnRename,
supportsOnSeriesDelete,
supportsOnEpisodeFileDelete,
supportsOnEpisodeFileDeleteForUpgrade,
supportsOnApplicationUpdate,
supportsOnHealthIssue,
includeHealthWarnings
} = item;
return (
<FormGroup>
<FormLabel>Notification Triggers</FormLabel>
<div>
<FormInputHelpText
text="Select which events should trigger this notification"
link="https://wiki.servarr.com/sonarr/settings#connections"
/>
<div className={styles.events}>
<div>
<FormInputGroup
type={inputTypes.CHECK}
name="onGrab"
helpText="On Grab"
isDisabled={!supportsOnGrab.value}
{...onGrab}
onChange={onInputChange}
/>
</div>
<div>
<FormInputGroup
type={inputTypes.CHECK}
name="onDownload"
helpText="On Download"
isDisabled={!supportsOnDownload.value}
{...onDownload}
onChange={onInputChange}
/>
</div>
{
onDownload.value &&
<div>
<FormInputGroup
type={inputTypes.CHECK}
name="onUpgrade"
helpText="On Upgrade"
isDisabled={!supportsOnUpgrade.value}
{...onUpgrade}
onChange={onInputChange}
/>
</div>
}
<div>
<FormInputGroup
type={inputTypes.CHECK}
name="onRename"
helpText="On Rename"
isDisabled={!supportsOnRename.value}
{...onRename}
onChange={onInputChange}
/>
</div>
<div>
<FormInputGroup
type={inputTypes.CHECK}
name="onSeriesDelete"
helpText="On Series Delete"
isDisabled={!supportsOnSeriesDelete.value}
{...onSeriesDelete}
onChange={onInputChange}
/>
</div>
<div>
<FormInputGroup
type={inputTypes.CHECK}
name="onEpisodeFileDelete"
helpText="On Episode File Delete"
isDisabled={!supportsOnEpisodeFileDelete.value}
{...onEpisodeFileDelete}
onChange={onInputChange}
/>
</div>
{
onEpisodeFileDelete.value &&
<div>
<FormInputGroup
type={inputTypes.CHECK}
name="onEpisodeFileDeleteForUpgrade"
helpText="On Episode File Delete For Upgrade"
isDisabled={!supportsOnEpisodeFileDeleteForUpgrade.value}
{...onEpisodeFileDeleteForUpgrade}
onChange={onInputChange}
/>
</div>
}
<div>
<FormInputGroup
type={inputTypes.CHECK}
name="onHealthIssue"
helpText="On Health Issue"
isDisabled={!supportsOnHealthIssue.value}
{...onHealthIssue}
onChange={onInputChange}
/>
</div>
{
onHealthIssue.value &&
<div>
<FormInputGroup
type={inputTypes.CHECK}
name="includeHealthWarnings"
helpText="Include Health Warnings"
isDisabled={!supportsOnHealthIssue.value}
{...includeHealthWarnings}
onChange={onInputChange}
/>
</div>
}
<div>
<FormInputGroup
type={inputTypes.CHECK}
name="onApplicationUpdate"
helpText="On Application Update"
isDisabled={!supportsOnApplicationUpdate.value}
{...onApplicationUpdate}
onChange={onInputChange}
/>
</div>
</div>
</div>
</FormGroup>
);
}
NotificationEventItems.propTypes = {
item: PropTypes.object.isRequired,
onInputChange: PropTypes.func.isRequired
};
export default NotificationEventItems;

View File

@ -1,13 +1,13 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { icons } from 'Helpers/Props';
import FieldSet from 'Components/FieldSet';
import Card from 'Components/Card'; import Card from 'Components/Card';
import FieldSet from 'Components/FieldSet';
import Icon from 'Components/Icon'; import Icon from 'Components/Icon';
import PageSectionContent from 'Components/Page/PageSectionContent'; import PageSectionContent from 'Components/Page/PageSectionContent';
import Notification from './Notification'; import { icons } from 'Helpers/Props';
import AddNotificationModal from './AddNotificationModal'; import AddNotificationModal from './AddNotificationModal';
import EditNotificationModalConnector from './EditNotificationModalConnector'; import EditNotificationModalConnector from './EditNotificationModalConnector';
import Notification from './Notification';
import styles from './Notifications.css'; import styles from './Notifications.css';
class Notifications extends Component { class Notifications extends Component {

View File

@ -2,9 +2,9 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react'; import React, { Component } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import sortByName from 'Utilities/Array/sortByName'; import { deleteNotification, fetchNotifications } from 'Store/Actions/settingsActions';
import createSortedSectionSelector from 'Store/Selectors/createSortedSectionSelector'; import createSortedSectionSelector from 'Store/Selectors/createSortedSectionSelector';
import { fetchNotifications, deleteNotification } from 'Store/Actions/settingsActions'; import sortByName from 'Utilities/Array/sortByName';
import Notifications from './Notifications'; import Notifications from './Notifications';
function createMapStateToProps() { function createMapStateToProps() {

View File

@ -109,6 +109,7 @@ export default {
selectedSchema.onSeriesDelete = selectedSchema.supportsOnSeriesDelete; selectedSchema.onSeriesDelete = selectedSchema.supportsOnSeriesDelete;
selectedSchema.onEpisodeFileDelete = selectedSchema.supportsOnEpisodeFileDelete; selectedSchema.onEpisodeFileDelete = selectedSchema.supportsOnEpisodeFileDelete;
selectedSchema.onEpisodeFileDeleteForUpgrade = selectedSchema.supportsOnEpisodeFileDeleteForUpgrade; selectedSchema.onEpisodeFileDeleteForUpgrade = selectedSchema.supportsOnEpisodeFileDeleteForUpgrade;
selectedSchema.onApplicationUpdate = selectedSchema.supportsOnApplicationUpdate;
return selectedSchema; return selectedSchema;
}); });

View File

@ -79,6 +79,11 @@ namespace NzbDrone.Core.Test.NotificationTests
TestLogger.Info("OnHealthIssue was called"); TestLogger.Info("OnHealthIssue was called");
} }
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{
TestLogger.Info("OnApplicationUpdate was called");
}
} }
class TestNotificationWithNoEvents : NotificationBase<TestSetting> class TestNotificationWithNoEvents : NotificationBase<TestSetting>
@ -92,7 +97,7 @@ namespace NzbDrone.Core.Test.NotificationTests
throw new NotImplementedException(); throw new NotImplementedException();
} }
} }
[Test] [Test]
@ -120,6 +125,7 @@ namespace NzbDrone.Core.Test.NotificationTests
notification.SupportsOnEpisodeFileDelete.Should().BeTrue(); notification.SupportsOnEpisodeFileDelete.Should().BeTrue();
notification.SupportsOnEpisodeFileDeleteForUpgrade.Should().BeTrue(); notification.SupportsOnEpisodeFileDeleteForUpgrade.Should().BeTrue();
notification.SupportsOnHealthIssue.Should().BeTrue(); notification.SupportsOnHealthIssue.Should().BeTrue();
notification.SupportsOnApplicationUpdate.Should().BeTrue();
} }
@ -136,6 +142,7 @@ namespace NzbDrone.Core.Test.NotificationTests
notification.SupportsOnEpisodeFileDelete.Should().BeFalse(); notification.SupportsOnEpisodeFileDelete.Should().BeFalse();
notification.SupportsOnEpisodeFileDeleteForUpgrade.Should().BeFalse(); notification.SupportsOnEpisodeFileDeleteForUpgrade.Should().BeFalse();
notification.SupportsOnHealthIssue.Should().BeFalse(); notification.SupportsOnHealthIssue.Should().BeFalse();
notification.SupportsOnApplicationUpdate.Should().BeFalse();
} }
} }

View File

@ -0,0 +1,14 @@
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(165)]
public class add_on_update_to_notifications : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Alter.Table("Notifications").AddColumn("OnApplicationUpdate").AsBoolean().WithDefaultValue(0);
}
}
}

View File

@ -76,7 +76,8 @@ namespace NzbDrone.Core.Datastore
.Ignore(i => i.SupportsOnSeriesDelete) .Ignore(i => i.SupportsOnSeriesDelete)
.Ignore(i => i.SupportsOnEpisodeFileDelete) .Ignore(i => i.SupportsOnEpisodeFileDelete)
.Ignore(i => i.SupportsOnEpisodeFileDeleteForUpgrade) .Ignore(i => i.SupportsOnEpisodeFileDeleteForUpgrade)
.Ignore(i => i.SupportsOnHealthIssue); .Ignore(i => i.SupportsOnHealthIssue)
.Ignore(i => i.SupportsOnApplicationUpdate);
Mapper.Entity<MetadataDefinition>().RegisterDefinition("Metadata") Mapper.Entity<MetadataDefinition>().RegisterDefinition("Metadata")
.Ignore(d => d.Tags); .Ignore(d => d.Tags);

View File

@ -0,0 +1,16 @@
using System;
namespace NzbDrone.Core.Notifications
{
public class ApplicationUpdateMessage
{
public string Message { get; set; }
public Version PreviousVersion { get; set; }
public Version NewVersion { get; set; }
public override string ToString()
{
return NewVersion.ToString();
}
}
}

View File

@ -23,7 +23,7 @@ namespace NzbDrone.Core.Notifications.Boxcar
public override void OnDownload(DownloadMessage message) public override void OnDownload(DownloadMessage message)
{ {
_proxy.SendNotification(EPISODE_DOWNLOADED_TITLE , message.Message, Settings); _proxy.SendNotification(EPISODE_DOWNLOADED_TITLE, message.Message, Settings);
} }
public override void OnEpisodeFileDelete(EpisodeDeleteMessage deleteMessage) public override void OnEpisodeFileDelete(EpisodeDeleteMessage deleteMessage)
@ -41,6 +41,10 @@ namespace NzbDrone.Core.Notifications.Boxcar
_proxy.SendNotification(HEALTH_ISSUE_TITLE, message.Message, Settings); _proxy.SendNotification(HEALTH_ISSUE_TITLE, message.Message, Settings);
} }
public override void OnApplicationUpdate(ApplicationUpdateMessage message)
{
_proxy.SendNotification(APPLICATION_UPDATE_TITLE, message.Message, Settings);
}
public override ValidationResult Test() public override ValidationResult Test()
{ {
var failures = new List<ValidationFailure>(); var failures = new List<ValidationFailure>();

View File

@ -198,6 +198,18 @@ namespace NzbDrone.Core.Notifications.CustomScript
ExecuteScript(environmentVariables); ExecuteScript(environmentVariables);
} }
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{
var environmentVariables = new StringDictionary();
environmentVariables.Add("Sonarr_EventType", "ApplicationUpdate");
environmentVariables.Add("Sonarr_Update_Message", updateMessage.Message);
environmentVariables.Add("Sonarr_Update_NewVersion", updateMessage.NewVersion.ToString());
environmentVariables.Add("Sonarr_Update_PreviousVersion", updateMessage.PreviousVersion.ToString());
ExecuteScript(environmentVariables);
}
public override ValidationResult Test() public override ValidationResult Test()
{ {
var failures = new List<ValidationFailure>(); var failures = new List<ValidationFailure>();

View File

@ -295,6 +295,40 @@ namespace NzbDrone.Core.Notifications.Discord
_proxy.SendPayload(payload, Settings); _proxy.SendPayload(payload, Settings);
} }
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{
var attachments = new List<Embed>
{
new Embed
{
Author = new DiscordAuthor
{
Name = Settings.Author.IsNullOrWhiteSpace() ? Environment.MachineName : Settings.Author,
IconUrl = "https://raw.githubusercontent.com/Sonarr/Sonarr/develop/Logo/256.png"
},
Title = APPLICATION_UPDATE_TITLE,
Timestamp = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ"),
Color = (int)DiscordColors.Standard,
Fields = new List<DiscordField>()
{
new DiscordField()
{
Name = "Previous Version",
Value = updateMessage.PreviousVersion.ToString()
},
new DiscordField()
{
Name = "New Version",
Value = updateMessage.NewVersion.ToString()
}
},
}
};
var payload = CreatePayload(null, attachments);
_proxy.SendPayload(payload, Settings);
}
public override ValidationResult Test() public override ValidationResult Test()
{ {
var failures = new List<ValidationFailure>(); var failures = new List<ValidationFailure>();

View File

@ -57,6 +57,12 @@ namespace NzbDrone.Core.Notifications.Email
SendEmail(Settings, HEALTH_ISSUE_TITLE_BRANDED, message.Message); SendEmail(Settings, HEALTH_ISSUE_TITLE_BRANDED, message.Message);
} }
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{
var body = $"{updateMessage.Message}";
SendEmail(Settings, APPLICATION_UPDATE_TITLE_BRANDED, body);
}
public override ValidationResult Test() public override ValidationResult Test()
{ {
var failures = new List<ValidationFailure>(); var failures = new List<ValidationFailure>();

View File

@ -44,6 +44,11 @@ namespace NzbDrone.Core.Notifications.Gotify
_proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings); _proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings);
} }
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{
_proxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings);
}
public override ValidationResult Test() public override ValidationResult Test()
{ {
var failures = new List<ValidationFailure>(); var failures = new List<ValidationFailure>();

View File

@ -15,6 +15,7 @@ namespace NzbDrone.Core.Notifications
void OnEpisodeFileDelete(EpisodeDeleteMessage deleteMessage); void OnEpisodeFileDelete(EpisodeDeleteMessage deleteMessage);
void OnSeriesDelete(SeriesDeleteMessage deleteMessage); void OnSeriesDelete(SeriesDeleteMessage deleteMessage);
void OnHealthIssue(HealthCheck.HealthCheck healthCheck); void OnHealthIssue(HealthCheck.HealthCheck healthCheck);
void OnApplicationUpdate(ApplicationUpdateMessage updateMessage);
void ProcessQueue(); void ProcessQueue();
bool SupportsOnGrab { get; } bool SupportsOnGrab { get; }
bool SupportsOnDownload { get; } bool SupportsOnDownload { get; }
@ -24,5 +25,6 @@ namespace NzbDrone.Core.Notifications
bool SupportsOnEpisodeFileDelete { get; } bool SupportsOnEpisodeFileDelete { get; }
bool SupportsOnEpisodeFileDeleteForUpgrade { get; } bool SupportsOnEpisodeFileDeleteForUpgrade { get; }
bool SupportsOnHealthIssue { get; } bool SupportsOnHealthIssue { get; }
bool SupportsOnApplicationUpdate { get; }
} }
} }

View File

@ -41,6 +41,11 @@ namespace NzbDrone.Core.Notifications.Join
_proxy.SendNotification(HEALTH_ISSUE_TITLE_BRANDED, message.Message, Settings); _proxy.SendNotification(HEALTH_ISSUE_TITLE_BRANDED, message.Message, Settings);
} }
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{
_proxy.SendNotification(APPLICATION_UPDATE_TITLE_BRANDED, updateMessage.Message, Settings);
}
public override ValidationResult Test() public override ValidationResult Test()
{ {
var failures = new List<ValidationFailure>(); var failures = new List<ValidationFailure>();

View File

@ -9,7 +9,7 @@ namespace NzbDrone.Core.Notifications.Mailgun
{ {
private readonly IMailgunProxy _proxy; private readonly IMailgunProxy _proxy;
private readonly Logger _logger; private readonly Logger _logger;
public MailGun(IMailgunProxy proxy, Logger logger) public MailGun(IMailgunProxy proxy, Logger logger)
{ {
_proxy = proxy; _proxy = proxy;
@ -48,6 +48,10 @@ namespace NzbDrone.Core.Notifications.Mailgun
_proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheckMessage.Message, Settings); _proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheckMessage.Message, Settings);
} }
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{
_proxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings);
}
public override ValidationResult Test() public override ValidationResult Test()
{ {
@ -66,7 +70,7 @@ namespace NzbDrone.Core.Notifications.Mailgun
_logger.Error(ex, "Unable to send test message though Mailgun."); _logger.Error(ex, "Unable to send test message though Mailgun.");
failures.Add(new ValidationFailure("", "Unable to send test message though Mailgun.")); failures.Add(new ValidationFailure("", "Unable to send test message though Mailgun."));
} }
return new ValidationResult(failures); return new ValidationResult(failures);
} }
} }

View File

@ -82,6 +82,14 @@ namespace NzbDrone.Core.Notifications.Emby
} }
} }
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{
if (Settings.Notify)
{
_mediaBrowserService.Notify(Settings, APPLICATION_UPDATE_TITLE_BRANDED, updateMessage.Message);
}
}
public override ValidationResult Test() public override ValidationResult Test()
{ {
var failures = new List<ValidationFailure>(); var failures = new List<ValidationFailure>();

View File

@ -15,12 +15,14 @@ namespace NzbDrone.Core.Notifications
protected const string EPISODE_DELETED_TITLE = "Episode Deleted"; protected const string EPISODE_DELETED_TITLE = "Episode Deleted";
protected const string SERIES_DELETED_TITLE = "Series Deleted"; protected const string SERIES_DELETED_TITLE = "Series Deleted";
protected const string HEALTH_ISSUE_TITLE = "Health Check Failure"; protected const string HEALTH_ISSUE_TITLE = "Health Check Failure";
protected const string APPLICATION_UPDATE_TITLE = "Application Updated";
protected const string EPISODE_GRABBED_TITLE_BRANDED = "Sonarr - " + EPISODE_GRABBED_TITLE; protected const string EPISODE_GRABBED_TITLE_BRANDED = "Sonarr - " + EPISODE_GRABBED_TITLE;
protected const string EPISODE_DOWNLOADED_TITLE_BRANDED = "Sonarr - " + EPISODE_DOWNLOADED_TITLE; protected const string EPISODE_DOWNLOADED_TITLE_BRANDED = "Sonarr - " + EPISODE_DOWNLOADED_TITLE;
protected const string EPISODE_DELETED_TITLE_BRANDED = "Sonarr - " + EPISODE_DELETED_TITLE; protected const string EPISODE_DELETED_TITLE_BRANDED = "Sonarr - " + EPISODE_DELETED_TITLE;
protected const string SERIES_DELETED_TITLE_BRANDED = "Sonarr - " + SERIES_DELETED_TITLE; protected const string SERIES_DELETED_TITLE_BRANDED = "Sonarr - " + SERIES_DELETED_TITLE;
protected const string HEALTH_ISSUE_TITLE_BRANDED = "Sonarr - " + HEALTH_ISSUE_TITLE; protected const string HEALTH_ISSUE_TITLE_BRANDED = "Sonarr - " + HEALTH_ISSUE_TITLE;
protected const string APPLICATION_UPDATE_TITLE_BRANDED = "Sonarr - " + APPLICATION_UPDATE_TITLE;
public abstract string Name { get; } public abstract string Name { get; }
@ -65,6 +67,10 @@ namespace NzbDrone.Core.Notifications
} }
public virtual void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{
}
public virtual void ProcessQueue() public virtual void ProcessQueue()
{ {
@ -78,6 +84,7 @@ namespace NzbDrone.Core.Notifications
public bool SupportsOnEpisodeFileDelete => HasConcreteImplementation("OnEpisodeFileDelete"); public bool SupportsOnEpisodeFileDelete => HasConcreteImplementation("OnEpisodeFileDelete");
public bool SupportsOnEpisodeFileDeleteForUpgrade => SupportsOnEpisodeFileDelete; public bool SupportsOnEpisodeFileDeleteForUpgrade => SupportsOnEpisodeFileDelete;
public bool SupportsOnHealthIssue => HasConcreteImplementation("OnHealthIssue"); public bool SupportsOnHealthIssue => HasConcreteImplementation("OnHealthIssue");
public bool SupportsOnApplicationUpdate => HasConcreteImplementation("OnApplicationUpdate");
protected TSettings Settings => (TSettings)Definition.Settings; protected TSettings Settings => (TSettings)Definition.Settings;

View File

@ -12,6 +12,7 @@ namespace NzbDrone.Core.Notifications
public bool OnEpisodeFileDelete { get; set; } public bool OnEpisodeFileDelete { get; set; }
public bool OnEpisodeFileDeleteForUpgrade { get; set; } public bool OnEpisodeFileDeleteForUpgrade { get; set; }
public bool OnHealthIssue { get; set; } public bool OnHealthIssue { get; set; }
public bool OnApplicationUpdate { get; set; }
public bool SupportsOnGrab { get; set; } public bool SupportsOnGrab { get; set; }
public bool SupportsOnDownload { get; set; } public bool SupportsOnDownload { get; set; }
public bool SupportsOnUpgrade { get; set; } public bool SupportsOnUpgrade { get; set; }
@ -21,7 +22,8 @@ namespace NzbDrone.Core.Notifications
public bool SupportsOnEpisodeFileDeleteForUpgrade { get; set; } public bool SupportsOnEpisodeFileDeleteForUpgrade { get; set; }
public bool SupportsOnHealthIssue { get; set; } public bool SupportsOnHealthIssue { get; set; }
public bool IncludeHealthWarnings { get; set; } public bool IncludeHealthWarnings { get; set; }
public bool SupportsOnApplicationUpdate { get; set; }
public override bool Enable => OnGrab || OnDownload || (OnDownload && OnUpgrade) || OnSeriesDelete || OnEpisodeFileDelete || OnEpisodeFileDeleteForUpgrade || OnHealthIssue; public override bool Enable => OnGrab || OnDownload || (OnDownload && OnUpgrade) || OnSeriesDelete || OnEpisodeFileDelete || OnEpisodeFileDeleteForUpgrade || OnHealthIssue || OnApplicationUpdate;
} }
} }

View File

@ -17,6 +17,7 @@ namespace NzbDrone.Core.Notifications
List<INotification> OnEpisodeFileDeleteEnabled(); List<INotification> OnEpisodeFileDeleteEnabled();
List<INotification> OnEpisodeFileDeleteForUpgradeEnabled(); List<INotification> OnEpisodeFileDeleteForUpgradeEnabled();
List<INotification> OnHealthIssueEnabled(); List<INotification> OnHealthIssueEnabled();
List<INotification> OnApplicationUpdateEnabled();
} }
public class NotificationFactory : ProviderFactory<INotification, NotificationDefinition>, INotificationFactory public class NotificationFactory : ProviderFactory<INotification, NotificationDefinition>, INotificationFactory
@ -65,6 +66,11 @@ namespace NzbDrone.Core.Notifications
return GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnHealthIssue).ToList(); return GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnHealthIssue).ToList();
} }
public List<INotification> OnApplicationUpdateEnabled()
{
return GetAvailableProviders().Where(n => ((NotificationDefinition)n.Definition).OnApplicationUpdate).ToList();
}
public override void SetProviderCharacteristics(INotification provider, NotificationDefinition definition) public override void SetProviderCharacteristics(INotification provider, NotificationDefinition definition)
{ {
base.SetProviderCharacteristics(provider, definition); base.SetProviderCharacteristics(provider, definition);
@ -77,6 +83,7 @@ namespace NzbDrone.Core.Notifications
definition.SupportsOnEpisodeFileDelete = provider.SupportsOnEpisodeFileDelete; definition.SupportsOnEpisodeFileDelete = provider.SupportsOnEpisodeFileDelete;
definition.SupportsOnEpisodeFileDeleteForUpgrade = provider.SupportsOnEpisodeFileDeleteForUpgrade; definition.SupportsOnEpisodeFileDeleteForUpgrade = provider.SupportsOnEpisodeFileDeleteForUpgrade;
definition.SupportsOnHealthIssue = provider.SupportsOnHealthIssue; definition.SupportsOnHealthIssue = provider.SupportsOnHealthIssue;
definition.SupportsOnApplicationUpdate = provider.SupportsOnApplicationUpdate;
} }
} }
} }

View File

@ -11,6 +11,7 @@ using NzbDrone.Core.Qualities;
using NzbDrone.Core.ThingiProvider; using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Tv; using NzbDrone.Core.Tv;
using NzbDrone.Core.Tv.Events; using NzbDrone.Core.Tv.Events;
using NzbDrone.Core.Update.History.Events;
namespace NzbDrone.Core.Notifications namespace NzbDrone.Core.Notifications
{ {
@ -21,6 +22,7 @@ namespace NzbDrone.Core.Notifications
IHandle<SeriesDeletedEvent>, IHandle<SeriesDeletedEvent>,
IHandle<EpisodeFileDeletedEvent>, IHandle<EpisodeFileDeletedEvent>,
IHandle<HealthCheckFailedEvent>, IHandle<HealthCheckFailedEvent>,
IHandle<UpdateInstalledEvent>,
IHandleAsync<DeleteCompletedEvent>, IHandleAsync<DeleteCompletedEvent>,
IHandleAsync<DownloadsProcessedEvent>, IHandleAsync<DownloadsProcessedEvent>,
IHandleAsync<RenameCompletedEvent>, IHandleAsync<RenameCompletedEvent>,
@ -193,6 +195,26 @@ namespace NzbDrone.Core.Notifications
} }
} }
public void Handle(UpdateInstalledEvent message)
{
var updateMessage = new ApplicationUpdateMessage();
updateMessage.Message = $"Sonarr updated from {message.PreviousVerison.ToString()} to {message.NewVersion.ToString()}";
updateMessage.PreviousVersion = message.PreviousVerison;
updateMessage.NewVersion = message.NewVersion;
foreach (var notification in _notificationFactory.OnApplicationUpdateEnabled())
{
try
{
notification.OnApplicationUpdate(updateMessage);
}
catch (Exception ex)
{
_logger.Warn(ex, "Unable to send OnApplicationUpdate notification to: " + notification.Definition.Name);
}
}
}
public void Handle(EpisodeFileDeletedEvent message) public void Handle(EpisodeFileDeletedEvent message)
{ {
if (message.EpisodeFile.Episodes.Value.Empty()) if (message.EpisodeFile.Episodes.Value.Empty())
@ -229,7 +251,7 @@ namespace NzbDrone.Core.Notifications
public void Handle(SeriesDeletedEvent message) public void Handle(SeriesDeletedEvent message)
{ {
var deleteMessage = new SeriesDeleteMessage(message.Series,message.DeleteFiles); var deleteMessage = new SeriesDeleteMessage(message.Series, message.DeleteFiles);
foreach (var notification in _notificationFactory.OnSeriesDeleteEnabled()) foreach (var notification in _notificationFactory.OnSeriesDeleteEnabled())
{ {

View File

@ -41,6 +41,11 @@ namespace NzbDrone.Core.Notifications.Prowl
_prowlProxy.SendNotification(HEALTH_ISSUE_TITLE, message.Message, Settings); _prowlProxy.SendNotification(HEALTH_ISSUE_TITLE, message.Message, Settings);
} }
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{
_prowlProxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings);
}
public override ValidationResult Test() public override ValidationResult Test()
{ {
var failures = new List<ValidationFailure>(); var failures = new List<ValidationFailure>();

View File

@ -43,6 +43,11 @@ namespace NzbDrone.Core.Notifications.PushBullet
_proxy.SendNotification(HEALTH_ISSUE_TITLE_BRANDED, healthCheck.Message, Settings); _proxy.SendNotification(HEALTH_ISSUE_TITLE_BRANDED, healthCheck.Message, Settings);
} }
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{
_proxy.SendNotification(APPLICATION_UPDATE_TITLE_BRANDED, updateMessage.Message, Settings);
}
public override ValidationResult Test() public override ValidationResult Test()
{ {
var failures = new List<ValidationFailure>(); var failures = new List<ValidationFailure>();
@ -60,23 +65,23 @@ namespace NzbDrone.Core.Notifications.PushBullet
if (Settings.ApiKey.IsNullOrWhiteSpace()) if (Settings.ApiKey.IsNullOrWhiteSpace())
{ {
return new return new
{ {
devices = new List<object>() devices = new List<object>()
}; };
} }
Settings.Validate().Filter("ApiKey").ThrowOnError(); Settings.Validate().Filter("ApiKey").ThrowOnError();
var devices = _proxy.GetDevices(Settings); var devices = _proxy.GetDevices(Settings);
return new return new
{ {
options = devices.Where(d => d.Nickname.IsNotNullOrWhiteSpace()) options = devices.Where(d => d.Nickname.IsNotNullOrWhiteSpace())
.OrderBy(d => d.Nickname, StringComparer.InvariantCultureIgnoreCase) .OrderBy(d => d.Nickname, StringComparer.InvariantCultureIgnoreCase)
.Select(d => new .Select(d => new
{ {
id = d.Id, id = d.Id,
name = d.Nickname name = d.Nickname
}) })
}; };
} }

View File

@ -7,7 +7,7 @@ namespace NzbDrone.Core.Notifications.Pushover
public class Pushover : NotificationBase<PushoverSettings> public class Pushover : NotificationBase<PushoverSettings>
{ {
private readonly IPushoverProxy _proxy; private readonly IPushoverProxy _proxy;
public Pushover(IPushoverProxy proxy) public Pushover(IPushoverProxy proxy)
{ {
_proxy = proxy; _proxy = proxy;
@ -30,7 +30,7 @@ namespace NzbDrone.Core.Notifications.Pushover
{ {
_proxy.SendNotification(EPISODE_DELETED_TITLE, deleteMessage.Message, Settings); _proxy.SendNotification(EPISODE_DELETED_TITLE, deleteMessage.Message, Settings);
} }
public override void OnSeriesDelete(SeriesDeleteMessage deleteMessage) public override void OnSeriesDelete(SeriesDeleteMessage deleteMessage)
{ {
_proxy.SendNotification(SERIES_DELETED_TITLE, deleteMessage.Message, Settings); _proxy.SendNotification(SERIES_DELETED_TITLE, deleteMessage.Message, Settings);
@ -41,6 +41,11 @@ namespace NzbDrone.Core.Notifications.Pushover
_proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings); _proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings);
} }
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{
_proxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings);
}
public override ValidationResult Test() public override ValidationResult Test()
{ {
var failures = new List<ValidationFailure>(); var failures = new List<ValidationFailure>();

View File

@ -43,6 +43,11 @@ namespace NzbDrone.Core.Notifications.SendGrid
_proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings); _proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings);
} }
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{
_proxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings);
}
public override ValidationResult Test() public override ValidationResult Test()
{ {
var failures = new List<ValidationFailure>(); var failures = new List<ValidationFailure>();

View File

@ -120,6 +120,23 @@ namespace NzbDrone.Core.Notifications.Slack
_proxy.SendPayload(payload, Settings); _proxy.SendPayload(payload, Settings);
} }
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{
var attachments = new List<Attachment>
{
new Attachment
{
Title = Environment.MachineName,
Text = updateMessage.Message,
Color = "good"
}
};
var payload = CreatePayload("Application Updated", attachments);
_proxy.SendPayload(payload, Settings);
}
public override ValidationResult Test() public override ValidationResult Test()
{ {
var failures = new List<ValidationFailure>(); var failures = new List<ValidationFailure>();

View File

@ -41,6 +41,11 @@ namespace NzbDrone.Core.Notifications.Telegram
_proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings); _proxy.SendNotification(HEALTH_ISSUE_TITLE, healthCheck.Message, Settings);
} }
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{
_proxy.SendNotification(APPLICATION_UPDATE_TITLE, updateMessage.Message, Settings);
}
public override ValidationResult Test() public override ValidationResult Test()
{ {
var failures = new List<ValidationFailure>(); var failures = new List<ValidationFailure>();

View File

@ -44,6 +44,11 @@ namespace NzbDrone.Core.Notifications.Twitter
_twitterService.SendNotification($"Health Issue: {healthCheck.Message}", Settings); _twitterService.SendNotification($"Health Issue: {healthCheck.Message}", Settings);
} }
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{
_twitterService.SendNotification($"Application Updated: {updateMessage.Message}", Settings);
}
public override object RequestAction(string action, IDictionary<string, string> query) public override object RequestAction(string action, IDictionary<string, string> query)
{ {
if (action == "startOAuth") if (action == "startOAuth")

View File

@ -56,10 +56,10 @@ namespace NzbDrone.Core.Notifications.Webhook
if (message.OldFiles.Any()) if (message.OldFiles.Any())
{ {
payload.DeletedFiles = message.OldFiles.ConvertAll(x => new WebhookEpisodeFile(x) payload.DeletedFiles = message.OldFiles.ConvertAll(x => new WebhookEpisodeFile(x)
{ {
Path = Path.Combine(message.Series.Path, Path = Path.Combine(message.Series.Path,
x.RelativePath) x.RelativePath)
} }
); );
} }
@ -86,7 +86,7 @@ namespace NzbDrone.Core.Notifications.Webhook
Series = new WebhookSeries(deleteMessage.Series), Series = new WebhookSeries(deleteMessage.Series),
Episodes = deleteMessage.EpisodeFile.Episodes.Value.ConvertAll(x => new WebhookEpisode(x)), Episodes = deleteMessage.EpisodeFile.Episodes.Value.ConvertAll(x => new WebhookEpisode(x)),
EpisodeFile = deleteMessage.EpisodeFile, EpisodeFile = deleteMessage.EpisodeFile,
DeleteReason = deleteMessage.Reason DeleteReason = deleteMessage.Reason
}; };
_proxy.SendWebhook(payload, Settings); _proxy.SendWebhook(payload, Settings);
@ -107,13 +107,26 @@ namespace NzbDrone.Core.Notifications.Webhook
public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck) public override void OnHealthIssue(HealthCheck.HealthCheck healthCheck)
{ {
var payload = new WebhookHealthPayload var payload = new WebhookHealthPayload
{ {
EventType = WebhookEventType.Health, EventType = WebhookEventType.Health,
Level = healthCheck.Type, Level = healthCheck.Type,
Message = healthCheck.Message, Message = healthCheck.Message,
Type = healthCheck.Source.Name, Type = healthCheck.Source.Name,
WikiUrl = healthCheck.WikiUrl?.ToString() WikiUrl = healthCheck.WikiUrl?.ToString()
}; };
_proxy.SendWebhook(payload, Settings);
}
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{
var payload = new WebhookApplicationUpdatePayload
{
EventType = WebhookEventType.ApplicationUpdate,
Message = updateMessage.Message,
PreviousVersion = updateMessage.PreviousVersion.ToString(),
NewVersion = updateMessage.NewVersion.ToString()
};
_proxy.SendWebhook(payload, Settings); _proxy.SendWebhook(payload, Settings);
} }
@ -134,16 +147,16 @@ namespace NzbDrone.Core.Notifications.Webhook
try try
{ {
var payload = new WebhookGrabPayload var payload = new WebhookGrabPayload
{
EventType = WebhookEventType.Test,
Series = new WebhookSeries()
{ {
EventType = WebhookEventType.Test, Id = 1,
Series = new WebhookSeries() Title = "Test Title",
{ Path = "C:\\testpath",
Id = 1, TvdbId = 1234
Title = "Test Title", },
Path = "C:\\testpath", Episodes = new List<WebhookEpisode>() {
TvdbId = 1234
},
Episodes = new List<WebhookEpisode>() {
new WebhookEpisode() new WebhookEpisode()
{ {
Id = 123, Id = 123,
@ -152,7 +165,7 @@ namespace NzbDrone.Core.Notifications.Webhook
Title = "Test title" Title = "Test title"
} }
} }
}; };
_proxy.SendWebhook(payload, Settings); _proxy.SendWebhook(payload, Settings);
} }

View File

@ -0,0 +1,11 @@
using NzbDrone.Core.HealthCheck;
namespace NzbDrone.Core.Notifications.Webhook
{
public class WebhookApplicationUpdatePayload : WebhookPayload
{
public string Message { get; set; }
public string PreviousVersion { get; set; }
public string NewVersion { get; set; }
}
}

View File

@ -14,6 +14,7 @@ namespace NzbDrone.Core.Notifications.Webhook
Rename, Rename,
SeriesDelete, SeriesDelete,
EpisodeFileDelete, EpisodeFileDelete,
Health Health,
ApplicationUpdate
} }
} }

View File

@ -66,6 +66,11 @@ namespace NzbDrone.Core.Notifications.Xbmc
Notify(Settings, HEALTH_ISSUE_TITLE_BRANDED, healthCheck.Message); Notify(Settings, HEALTH_ISSUE_TITLE_BRANDED, healthCheck.Message);
} }
public override void OnApplicationUpdate(ApplicationUpdateMessage updateMessage)
{
Notify(Settings, APPLICATION_UPDATE_TITLE_BRANDED, updateMessage.Message);
}
public override string Name => "Kodi"; public override string Name => "Kodi";
public override ValidationResult Test() public override ValidationResult Test()

View File

@ -13,6 +13,7 @@ namespace Sonarr.Api.V3.Notifications
public bool OnEpisodeFileDelete { get; set; } public bool OnEpisodeFileDelete { get; set; }
public bool OnEpisodeFileDeleteForUpgrade { get; set; } public bool OnEpisodeFileDeleteForUpgrade { get; set; }
public bool OnHealthIssue { get; set; } public bool OnHealthIssue { get; set; }
public bool OnApplicationUpdate { get; set; }
public bool SupportsOnGrab { get; set; } public bool SupportsOnGrab { get; set; }
public bool SupportsOnDownload { get; set; } public bool SupportsOnDownload { get; set; }
public bool SupportsOnUpgrade { get; set; } public bool SupportsOnUpgrade { get; set; }
@ -21,6 +22,7 @@ namespace Sonarr.Api.V3.Notifications
public bool SupportsOnEpisodeFileDelete { get; set; } public bool SupportsOnEpisodeFileDelete { get; set; }
public bool SupportsOnEpisodeFileDeleteForUpgrade { get; set; } public bool SupportsOnEpisodeFileDeleteForUpgrade { get; set; }
public bool SupportsOnHealthIssue { get; set; } public bool SupportsOnHealthIssue { get; set; }
public bool SupportsOnApplicationUpdate { get; set; }
public bool IncludeHealthWarnings { get; set; } public bool IncludeHealthWarnings { get; set; }
public string TestCommand { get; set; } public string TestCommand { get; set; }
} }
@ -41,6 +43,7 @@ namespace Sonarr.Api.V3.Notifications
resource.OnEpisodeFileDelete = definition.OnEpisodeFileDelete; resource.OnEpisodeFileDelete = definition.OnEpisodeFileDelete;
resource.OnEpisodeFileDeleteForUpgrade = definition.OnEpisodeFileDeleteForUpgrade; resource.OnEpisodeFileDeleteForUpgrade = definition.OnEpisodeFileDeleteForUpgrade;
resource.OnHealthIssue = definition.OnHealthIssue; resource.OnHealthIssue = definition.OnHealthIssue;
resource.OnApplicationUpdate = definition.OnApplicationUpdate;
resource.SupportsOnGrab = definition.SupportsOnGrab; resource.SupportsOnGrab = definition.SupportsOnGrab;
resource.SupportsOnDownload = definition.SupportsOnDownload; resource.SupportsOnDownload = definition.SupportsOnDownload;
resource.SupportsOnUpgrade = definition.SupportsOnUpgrade; resource.SupportsOnUpgrade = definition.SupportsOnUpgrade;
@ -50,6 +53,7 @@ namespace Sonarr.Api.V3.Notifications
resource.SupportsOnEpisodeFileDeleteForUpgrade = definition.SupportsOnEpisodeFileDeleteForUpgrade; resource.SupportsOnEpisodeFileDeleteForUpgrade = definition.SupportsOnEpisodeFileDeleteForUpgrade;
resource.SupportsOnHealthIssue = definition.SupportsOnHealthIssue; resource.SupportsOnHealthIssue = definition.SupportsOnHealthIssue;
resource.IncludeHealthWarnings = definition.IncludeHealthWarnings; resource.IncludeHealthWarnings = definition.IncludeHealthWarnings;
resource.SupportsOnApplicationUpdate = definition.SupportsOnApplicationUpdate;
return resource; return resource;
} }
@ -68,6 +72,7 @@ namespace Sonarr.Api.V3.Notifications
definition.OnEpisodeFileDelete = resource.OnEpisodeFileDelete; definition.OnEpisodeFileDelete = resource.OnEpisodeFileDelete;
definition.OnEpisodeFileDeleteForUpgrade = resource.OnEpisodeFileDeleteForUpgrade; definition.OnEpisodeFileDeleteForUpgrade = resource.OnEpisodeFileDeleteForUpgrade;
definition.OnHealthIssue = resource.OnHealthIssue; definition.OnHealthIssue = resource.OnHealthIssue;
definition.OnApplicationUpdate = resource.OnApplicationUpdate;
definition.SupportsOnGrab = resource.SupportsOnGrab; definition.SupportsOnGrab = resource.SupportsOnGrab;
definition.SupportsOnDownload = resource.SupportsOnDownload; definition.SupportsOnDownload = resource.SupportsOnDownload;
definition.SupportsOnUpgrade = resource.SupportsOnUpgrade; definition.SupportsOnUpgrade = resource.SupportsOnUpgrade;
@ -77,6 +82,7 @@ namespace Sonarr.Api.V3.Notifications
definition.SupportsOnEpisodeFileDeleteForUpgrade = resource.SupportsOnEpisodeFileDeleteForUpgrade; definition.SupportsOnEpisodeFileDeleteForUpgrade = resource.SupportsOnEpisodeFileDeleteForUpgrade;
definition.SupportsOnHealthIssue = resource.SupportsOnHealthIssue; definition.SupportsOnHealthIssue = resource.SupportsOnHealthIssue;
definition.IncludeHealthWarnings = resource.IncludeHealthWarnings; definition.IncludeHealthWarnings = resource.IncludeHealthWarnings;
definition.SupportsOnApplicationUpdate = resource.SupportsOnApplicationUpdate;
return definition; return definition;
} }