mirror of
https://github.com/Sonarr/Sonarr
synced 2025-03-12 07:07:47 +00:00
Gotify notification updates
New: Option to include links for Gotify notifications New: Include images and links for Android Closes #7190
This commit is contained in:
parent
750a9353f8
commit
3c857135c5
6 changed files with 169 additions and 33 deletions
|
@ -1347,6 +1347,10 @@
|
||||||
"NotificationsGotifySettingsAppToken": "App Token",
|
"NotificationsGotifySettingsAppToken": "App Token",
|
||||||
"NotificationsGotifySettingsAppTokenHelpText": "The Application Token generated by Gotify",
|
"NotificationsGotifySettingsAppTokenHelpText": "The Application Token generated by Gotify",
|
||||||
"NotificationsGotifySettingsPriorityHelpText": "Priority of the notification",
|
"NotificationsGotifySettingsPriorityHelpText": "Priority of the notification",
|
||||||
|
"NotificationsGotifySettingsMetadataLinks": "Metadata Links",
|
||||||
|
"NotificationsGotifySettingsMetadataLinksHelpText": "Add a links to series metadata when sending notifications",
|
||||||
|
"NotificationsGotifySettingsPreferredMetadataLink": "Preferred Metadata Link",
|
||||||
|
"NotificationsGotifySettingsPreferredMetadataLinkHelpText": "Metadata link for clients that only support a single link",
|
||||||
"NotificationsGotifySettingsServer": "Gotify Server",
|
"NotificationsGotifySettingsServer": "Gotify Server",
|
||||||
"NotificationsGotifySettingsServerHelpText": "Gotify server URL, including http(s):// and port if needed",
|
"NotificationsGotifySettingsServerHelpText": "Gotify server URL, including http(s):// and port if needed",
|
||||||
"NotificationsJoinSettingsApiKeyHelpText": "The API Key from your Join account settings (click Join API button).",
|
"NotificationsJoinSettingsApiKeyHelpText": "The API Key from your Join account settings (click Join API button).",
|
||||||
|
|
|
@ -4,6 +4,7 @@ using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using FluentValidation.Results;
|
using FluentValidation.Results;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.Localization;
|
using NzbDrone.Core.Localization;
|
||||||
using NzbDrone.Core.MediaCover;
|
using NzbDrone.Core.MediaCover;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
@ -12,6 +13,8 @@ namespace NzbDrone.Core.Notifications.Gotify
|
||||||
{
|
{
|
||||||
public class Gotify : NotificationBase<GotifySettings>
|
public class Gotify : NotificationBase<GotifySettings>
|
||||||
{
|
{
|
||||||
|
private const string SonarrImageUrl = "https://raw.githubusercontent.com/Sonarr/Sonarr/develop/Logo/128.png";
|
||||||
|
|
||||||
private readonly IGotifyProxy _proxy;
|
private readonly IGotifyProxy _proxy;
|
||||||
private readonly ILocalizationService _localizationService;
|
private readonly ILocalizationService _localizationService;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
@ -88,20 +91,30 @@ namespace NzbDrone.Core.Notifications.Gotify
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
sb.AppendLine("This is a test message from Sonarr");
|
sb.AppendLine("This is a test message from Sonarr");
|
||||||
|
|
||||||
|
var payload = new GotifyMessage
|
||||||
|
{
|
||||||
|
Title = title,
|
||||||
|
Priority = Settings.Priority
|
||||||
|
};
|
||||||
|
|
||||||
if (Settings.IncludeSeriesPoster)
|
if (Settings.IncludeSeriesPoster)
|
||||||
{
|
{
|
||||||
isMarkdown = true;
|
isMarkdown = true;
|
||||||
|
|
||||||
sb.AppendLine("\r");
|
sb.AppendLine($"\r");
|
||||||
|
payload.SetImage(SonarrImageUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
var payload = new GotifyMessage
|
if (Settings.MetadataLinks.Any())
|
||||||
{
|
{
|
||||||
Title = title,
|
isMarkdown = true;
|
||||||
Message = sb.ToString(),
|
|
||||||
Priority = Settings.Priority
|
|
||||||
};
|
|
||||||
|
|
||||||
|
sb.AppendLine("");
|
||||||
|
sb.AppendLine("[Sonarr.tv](https://sonarr.tv)");
|
||||||
|
payload.SetClickUrl("https://sonarr.tv");
|
||||||
|
}
|
||||||
|
|
||||||
|
payload.Message = sb.ToString();
|
||||||
payload.SetContentType(isMarkdown);
|
payload.SetContentType(isMarkdown);
|
||||||
|
|
||||||
_proxy.SendNotification(payload, Settings);
|
_proxy.SendNotification(payload, Settings);
|
||||||
|
@ -122,24 +135,72 @@ namespace NzbDrone.Core.Notifications.Gotify
|
||||||
|
|
||||||
sb.AppendLine(message);
|
sb.AppendLine(message);
|
||||||
|
|
||||||
if (Settings.IncludeSeriesPoster && series != null)
|
|
||||||
{
|
|
||||||
var poster = series.Images.FirstOrDefault(x => x.CoverType == MediaCoverTypes.Poster)?.RemoteUrl;
|
|
||||||
|
|
||||||
if (poster != null)
|
|
||||||
{
|
|
||||||
isMarkdown = true;
|
|
||||||
sb.AppendLine($"\r");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var payload = new GotifyMessage
|
var payload = new GotifyMessage
|
||||||
{
|
{
|
||||||
Title = title,
|
Title = title,
|
||||||
Message = sb.ToString(),
|
|
||||||
Priority = Settings.Priority
|
Priority = Settings.Priority
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (series != null)
|
||||||
|
{
|
||||||
|
if (Settings.IncludeSeriesPoster)
|
||||||
|
{
|
||||||
|
var poster = series.Images.FirstOrDefault(x => x.CoverType == MediaCoverTypes.Poster)?.RemoteUrl;
|
||||||
|
|
||||||
|
if (poster != null)
|
||||||
|
{
|
||||||
|
isMarkdown = true;
|
||||||
|
sb.AppendLine($"\r");
|
||||||
|
payload.SetImage(poster);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Settings.MetadataLinks.Any())
|
||||||
|
{
|
||||||
|
isMarkdown = true;
|
||||||
|
sb.AppendLine("");
|
||||||
|
|
||||||
|
foreach (var link in Settings.MetadataLinks)
|
||||||
|
{
|
||||||
|
var linkType = (MetadataLinkType)link;
|
||||||
|
var linkText = "";
|
||||||
|
var linkUrl = "";
|
||||||
|
|
||||||
|
if (linkType == MetadataLinkType.Imdb && series.ImdbId.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
linkText = "IMDb";
|
||||||
|
linkUrl = $"https://www.imdb.com/title/{series.ImdbId}";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (linkType == MetadataLinkType.Tvdb && series.TvdbId > 0)
|
||||||
|
{
|
||||||
|
linkText = "TVDb";
|
||||||
|
linkUrl = $"http://www.thetvdb.com/?tab=series&id={series.TvdbId}";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (linkType == MetadataLinkType.Trakt && series.TvdbId > 0)
|
||||||
|
{
|
||||||
|
linkText = "TVMaze";
|
||||||
|
linkUrl = $"http://trakt.tv/search/tvdb/{series.TvdbId}?id_type=show";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (linkType == MetadataLinkType.Tvmaze && series.TvMazeId > 0)
|
||||||
|
{
|
||||||
|
linkText = "Trakt";
|
||||||
|
linkUrl = $"http://www.tvmaze.com/shows/{series.TvMazeId}/_";
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.AppendLine($"[{linkText}]({linkUrl})");
|
||||||
|
|
||||||
|
if (link == Settings.PreferredMetadataLink)
|
||||||
|
{
|
||||||
|
payload.SetClickUrl(linkUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
payload.Message = sb.ToString();
|
||||||
payload.SetContentType(isMarkdown);
|
payload.SetContentType(isMarkdown);
|
||||||
|
|
||||||
_proxy.SendNotification(payload, Settings);
|
_proxy.SendNotification(payload, Settings);
|
||||||
|
|
|
@ -20,12 +20,27 @@ namespace NzbDrone.Core.Notifications.Gotify
|
||||||
|
|
||||||
Extras.ClientDisplay = new GotifyClientDisplay(contentType);
|
Extras.ClientDisplay = new GotifyClientDisplay(contentType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetImage(string imageUrl)
|
||||||
|
{
|
||||||
|
Extras.ClientNotification ??= new GotifyClientNotification();
|
||||||
|
Extras.ClientNotification.BigImageUrl = imageUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetClickUrl(string url)
|
||||||
|
{
|
||||||
|
Extras.ClientNotification ??= new GotifyClientNotification();
|
||||||
|
Extras.ClientNotification.Click = new GotifyClientNotificationClick(url);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class GotifyExtras
|
public class GotifyExtras
|
||||||
{
|
{
|
||||||
[JsonProperty("client::display")]
|
[JsonProperty("client::display")]
|
||||||
public GotifyClientDisplay ClientDisplay { get; set; }
|
public GotifyClientDisplay ClientDisplay { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("client::notification")]
|
||||||
|
public GotifyClientNotification ClientNotification { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class GotifyClientDisplay
|
public class GotifyClientDisplay
|
||||||
|
@ -37,4 +52,20 @@ namespace NzbDrone.Core.Notifications.Gotify
|
||||||
ContentType = contentType;
|
ContentType = contentType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class GotifyClientNotification
|
||||||
|
{
|
||||||
|
public string BigImageUrl { get; set; }
|
||||||
|
public GotifyClientNotificationClick Click { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GotifyClientNotificationClick
|
||||||
|
{
|
||||||
|
public string Url { get; set; }
|
||||||
|
|
||||||
|
public GotifyClientNotificationClick(string url)
|
||||||
|
{
|
||||||
|
Url = url;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.Annotations;
|
using NzbDrone.Core.Annotations;
|
||||||
using NzbDrone.Core.Validation;
|
using NzbDrone.Core.Validation;
|
||||||
|
|
||||||
|
@ -10,6 +14,30 @@ namespace NzbDrone.Core.Notifications.Gotify
|
||||||
{
|
{
|
||||||
RuleFor(c => c.Server).IsValidUrl();
|
RuleFor(c => c.Server).IsValidUrl();
|
||||||
RuleFor(c => c.AppToken).NotEmpty();
|
RuleFor(c => c.AppToken).NotEmpty();
|
||||||
|
|
||||||
|
RuleFor(c => c.MetadataLinks).Custom((links, context) =>
|
||||||
|
{
|
||||||
|
foreach (var link in links)
|
||||||
|
{
|
||||||
|
if (!Enum.IsDefined(typeof(MetadataLinkType), link))
|
||||||
|
{
|
||||||
|
context.AddFailure("MetadataLinks", $"MetadataLink is not valid: {link}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RuleFor(c => c).Custom((c, context) =>
|
||||||
|
{
|
||||||
|
if (c.MetadataLinks.Empty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!c.MetadataLinks.Contains(c.PreferredMetadataLink))
|
||||||
|
{
|
||||||
|
context.AddFailure("PreferredMetadataLink", "Must be a selected link");
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +48,8 @@ namespace NzbDrone.Core.Notifications.Gotify
|
||||||
public GotifySettings()
|
public GotifySettings()
|
||||||
{
|
{
|
||||||
Priority = 5;
|
Priority = 5;
|
||||||
|
MetadataLinks = Enumerable.Empty<int>();
|
||||||
|
PreferredMetadataLink = (int)MetadataLinkType.Tvdb;
|
||||||
}
|
}
|
||||||
|
|
||||||
[FieldDefinition(0, Label = "NotificationsGotifySettingsServer", HelpText = "NotificationsGotifySettingsServerHelpText")]
|
[FieldDefinition(0, Label = "NotificationsGotifySettingsServer", HelpText = "NotificationsGotifySettingsServerHelpText")]
|
||||||
|
@ -34,6 +64,12 @@ namespace NzbDrone.Core.Notifications.Gotify
|
||||||
[FieldDefinition(3, Label = "NotificationsGotifySettingIncludeSeriesPoster", Type = FieldType.Checkbox, HelpText = "NotificationsGotifySettingIncludeSeriesPosterHelpText")]
|
[FieldDefinition(3, Label = "NotificationsGotifySettingIncludeSeriesPoster", Type = FieldType.Checkbox, HelpText = "NotificationsGotifySettingIncludeSeriesPosterHelpText")]
|
||||||
public bool IncludeSeriesPoster { get; set; }
|
public bool IncludeSeriesPoster { get; set; }
|
||||||
|
|
||||||
|
[FieldDefinition(4, Label = "NotificationsGotifySettingsMetadataLinks", Type = FieldType.Select, SelectOptions = typeof(MetadataLinkType), HelpText = "NotificationsGotifySettingsMetadataLinksHelpText")]
|
||||||
|
public IEnumerable<int> MetadataLinks { get; set; }
|
||||||
|
|
||||||
|
[FieldDefinition(5, Label = "NotificationsGotifySettingsPreferredMetadataLink", Type = FieldType.Select, SelectOptions = typeof(MetadataLinkType), HelpText = "NotificationsGotifySettingsPreferredMetadataLinkHelpText")]
|
||||||
|
public int PreferredMetadataLink { get; set; }
|
||||||
|
|
||||||
public override NzbDroneValidationResult Validate()
|
public override NzbDroneValidationResult Validate()
|
||||||
{
|
{
|
||||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||||
|
|
19
src/NzbDrone.Core/Notifications/MetadataLinkType.cs
Normal file
19
src/NzbDrone.Core/Notifications/MetadataLinkType.cs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
using NzbDrone.Core.Annotations;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Notifications
|
||||||
|
{
|
||||||
|
public enum MetadataLinkType
|
||||||
|
{
|
||||||
|
[FieldOption(Label = "IMDb")]
|
||||||
|
Imdb = 0,
|
||||||
|
|
||||||
|
[FieldOption(Label = "TVDb")]
|
||||||
|
Tvdb = 1,
|
||||||
|
|
||||||
|
[FieldOption(Label = "TVMaze")]
|
||||||
|
Tvmaze = 2,
|
||||||
|
|
||||||
|
[FieldOption(Label = "Trakt")]
|
||||||
|
Trakt = 3
|
||||||
|
}
|
||||||
|
}
|
|
@ -59,19 +59,4 @@ namespace NzbDrone.Core.Notifications.Telegram
|
||||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum MetadataLinkType
|
|
||||||
{
|
|
||||||
[FieldOption(Label = "IMDb")]
|
|
||||||
Imdb,
|
|
||||||
|
|
||||||
[FieldOption(Label = "TVDb")]
|
|
||||||
Tvdb,
|
|
||||||
|
|
||||||
[FieldOption(Label = "TVMaze")]
|
|
||||||
Tvmaze,
|
|
||||||
|
|
||||||
[FieldOption(Label = "Trakt")]
|
|
||||||
Trakt,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue