mirror of
https://github.com/jellyfin/jellyfin-plugin-webhook.git
synced 2024-11-23 05:59:58 +00:00
Update dependencies and fix stylecop (#138)
This commit is contained in:
parent
4ec22bd5a2
commit
4c454578ac
@ -10,78 +10,77 @@ using Jellyfin.Plugin.Webhook.Destinations.Slack;
|
||||
using Jellyfin.Plugin.Webhook.Destinations.Smtp;
|
||||
using MediaBrowser.Model.Plugins;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Configuration
|
||||
namespace Jellyfin.Plugin.Webhook.Configuration;
|
||||
|
||||
/// <summary>
|
||||
/// Webhook plugin configuration.
|
||||
/// </summary>
|
||||
public class PluginConfiguration : BasePluginConfiguration
|
||||
{
|
||||
/// <summary>
|
||||
/// Webhook plugin configuration.
|
||||
/// Initializes a new instance of the <see cref="PluginConfiguration"/> class.
|
||||
/// </summary>
|
||||
public class PluginConfiguration : BasePluginConfiguration
|
||||
public PluginConfiguration()
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PluginConfiguration"/> class.
|
||||
/// </summary>
|
||||
public PluginConfiguration()
|
||||
{
|
||||
ServerUrl = string.Empty;
|
||||
DiscordOptions = Array.Empty<DiscordOption>();
|
||||
GenericOptions = Array.Empty<GenericOption>();
|
||||
GenericFormOptions = Array.Empty<GenericFormOption>();
|
||||
GotifyOptions = Array.Empty<GotifyOption>();
|
||||
PushbulletOptions = Array.Empty<PushbulletOption>();
|
||||
PushoverOptions = Array.Empty<PushoverOption>();
|
||||
SlackOptions = Array.Empty<SlackOption>();
|
||||
SmtpOptions = Array.Empty<SmtpOption>();
|
||||
MqttOptions = Array.Empty<MqttOption>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the jellyfin server url.
|
||||
/// </summary>
|
||||
public string ServerUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the discord options.
|
||||
/// </summary>
|
||||
public DiscordOption[] DiscordOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the generic options.
|
||||
/// </summary>
|
||||
public GenericOption[] GenericOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the generic form options.
|
||||
/// </summary>
|
||||
public GenericFormOption[] GenericFormOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the gotify options.
|
||||
/// </summary>
|
||||
public GotifyOption[] GotifyOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pushbullet options.
|
||||
/// </summary>
|
||||
public PushbulletOption[] PushbulletOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pushover options.
|
||||
/// </summary>
|
||||
public PushoverOption[] PushoverOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the slack options.
|
||||
/// </summary>
|
||||
public SlackOption[] SlackOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the smtp options.
|
||||
/// </summary>
|
||||
public SmtpOption[] SmtpOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the mqtt options.
|
||||
/// </summary>
|
||||
public MqttOption[] MqttOptions { get; set; }
|
||||
ServerUrl = string.Empty;
|
||||
DiscordOptions = Array.Empty<DiscordOption>();
|
||||
GenericOptions = Array.Empty<GenericOption>();
|
||||
GenericFormOptions = Array.Empty<GenericFormOption>();
|
||||
GotifyOptions = Array.Empty<GotifyOption>();
|
||||
PushbulletOptions = Array.Empty<PushbulletOption>();
|
||||
PushoverOptions = Array.Empty<PushoverOption>();
|
||||
SlackOptions = Array.Empty<SlackOption>();
|
||||
SmtpOptions = Array.Empty<SmtpOption>();
|
||||
MqttOptions = Array.Empty<MqttOption>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the jellyfin server url.
|
||||
/// </summary>
|
||||
public string ServerUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the discord options.
|
||||
/// </summary>
|
||||
public DiscordOption[] DiscordOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the generic options.
|
||||
/// </summary>
|
||||
public GenericOption[] GenericOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the generic form options.
|
||||
/// </summary>
|
||||
public GenericFormOption[] GenericFormOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the gotify options.
|
||||
/// </summary>
|
||||
public GotifyOption[] GotifyOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pushbullet options.
|
||||
/// </summary>
|
||||
public PushbulletOption[] PushbulletOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pushover options.
|
||||
/// </summary>
|
||||
public PushoverOption[] PushoverOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the slack options.
|
||||
/// </summary>
|
||||
public SlackOption[] SlackOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the smtp options.
|
||||
/// </summary>
|
||||
public SmtpOption[] SmtpOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the mqtt options.
|
||||
/// </summary>
|
||||
public MqttOption[] MqttOptions { get; set; }
|
||||
}
|
||||
|
@ -2,39 +2,38 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations;
|
||||
|
||||
/// <summary>
|
||||
/// The base destination.
|
||||
/// </summary>
|
||||
public class BaseClient
|
||||
{
|
||||
/// <summary>
|
||||
/// The base destination.
|
||||
/// Determines whether the client should send the webhook.
|
||||
/// </summary>
|
||||
public class BaseClient
|
||||
/// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param>
|
||||
/// <param name="option">The sender option.</param>
|
||||
/// <param name="data">The webhook data.</param>
|
||||
/// <returns>Whether the client should send the webhook.</returns>
|
||||
protected bool SendWebhook(
|
||||
ILogger logger,
|
||||
BaseOption option,
|
||||
Dictionary<string, object> data)
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines whether the client should send the webhook.
|
||||
/// </summary>
|
||||
/// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param>
|
||||
/// <param name="option">The sender option.</param>
|
||||
/// <param name="data">The webhook data.</param>
|
||||
/// <returns>Whether the client should send the webhook.</returns>
|
||||
protected bool SendWebhook(
|
||||
ILogger logger,
|
||||
BaseOption option,
|
||||
Dictionary<string, object> data)
|
||||
var notificationType = data[nameof(NotificationType)] as NotificationType? ?? NotificationType.None;
|
||||
|
||||
// Don't filter on UserId if the notification type is UserCreated.
|
||||
if (notificationType is not NotificationType.UserCreated
|
||||
&& option.UserFilter.Length is not 0
|
||||
&& data.TryGetValue("UserId", out var userIdObj)
|
||||
&& userIdObj is Guid userId
|
||||
&& Array.IndexOf(option.UserFilter, userId) is -1)
|
||||
{
|
||||
var notificationType = data[nameof(NotificationType)] as NotificationType? ?? NotificationType.None;
|
||||
|
||||
// Don't filter on UserId if the notification type is UserCreated.
|
||||
if (notificationType is not NotificationType.UserCreated
|
||||
&& option.UserFilter.Length is not 0
|
||||
&& data.TryGetValue("UserId", out var userIdObj)
|
||||
&& userIdObj is Guid userId
|
||||
&& Array.IndexOf(option.UserFilter, userId) is -1)
|
||||
{
|
||||
logger.LogDebug("UserId {UserId} not found in user filter, ignoring event", userId);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
logger.LogDebug("UserId {UserId} not found in user filter, ignoring event", userId);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -5,97 +5,96 @@ using HandlebarsDotNet;
|
||||
using Jellyfin.Extensions.Json;
|
||||
using Jellyfin.Plugin.Webhook.Helpers;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations;
|
||||
|
||||
/// <summary>
|
||||
/// Base options for destination.
|
||||
/// </summary>
|
||||
public abstract class BaseOption
|
||||
{
|
||||
private HandlebarsTemplate<object, string>? _compiledTemplate;
|
||||
|
||||
/// <summary>
|
||||
/// Base options for destination.
|
||||
/// Gets or sets the notification type.
|
||||
/// </summary>
|
||||
public abstract class BaseOption
|
||||
public NotificationType[] NotificationTypes { get; set; } = Array.Empty<NotificationType>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the webhook name.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Only used for display.
|
||||
/// </remarks>
|
||||
public string? WebhookName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the webhook uri.
|
||||
/// </summary>
|
||||
public string? WebhookUri { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to notify on movies.
|
||||
/// </summary>
|
||||
public bool EnableMovies { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to notify on episodes.
|
||||
/// </summary>
|
||||
public bool EnableEpisodes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to notify on series.
|
||||
/// </summary>
|
||||
public bool EnableSeries { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to notify on seasons.
|
||||
/// </summary>
|
||||
public bool EnableSeasons { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to notify on albums.
|
||||
/// </summary>
|
||||
public bool EnableAlbums { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to notify on songs.
|
||||
/// </summary>
|
||||
public bool EnableSongs { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to send all possible properties.
|
||||
/// </summary>
|
||||
public bool SendAllProperties { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the handlebars template.
|
||||
/// </summary>
|
||||
public string? Template { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the webhook user filter.
|
||||
/// </summary>
|
||||
public Guid[] UserFilter { get; set; } = Array.Empty<Guid>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the compiled handlebars template.
|
||||
/// </summary>
|
||||
/// <returns>The compiled handlebars template.</returns>
|
||||
public HandlebarsTemplate<object, string> GetCompiledTemplate()
|
||||
{
|
||||
private HandlebarsTemplate<object, string>? _compiledTemplate;
|
||||
return _compiledTemplate ??= Handlebars.Compile(HandlebarsFunctionHelpers.Base64Decode(Template));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the notification type.
|
||||
/// </summary>
|
||||
public NotificationType[] NotificationTypes { get; set; } = Array.Empty<NotificationType>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the webhook name.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Only used for display.
|
||||
/// </remarks>
|
||||
public string? WebhookName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the webhook uri.
|
||||
/// </summary>
|
||||
public string? WebhookUri { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to notify on movies.
|
||||
/// </summary>
|
||||
public bool EnableMovies { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to notify on episodes.
|
||||
/// </summary>
|
||||
public bool EnableEpisodes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to notify on series.
|
||||
/// </summary>
|
||||
public bool EnableSeries { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to notify on seasons.
|
||||
/// </summary>
|
||||
public bool EnableSeasons { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to notify on albums.
|
||||
/// </summary>
|
||||
public bool EnableAlbums { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to notify on songs.
|
||||
/// </summary>
|
||||
public bool EnableSongs { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to send all possible properties.
|
||||
/// </summary>
|
||||
public bool SendAllProperties { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the handlebars template.
|
||||
/// </summary>
|
||||
public string? Template { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the webhook user filter.
|
||||
/// </summary>
|
||||
public Guid[] UserFilter { get; set; } = Array.Empty<Guid>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the compiled handlebars template.
|
||||
/// </summary>
|
||||
/// <returns>The compiled handlebars template.</returns>
|
||||
public HandlebarsTemplate<object, string> GetCompiledTemplate()
|
||||
{
|
||||
return _compiledTemplate ??= Handlebars.Compile(HandlebarsFunctionHelpers.Base64Decode(Template));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the message body.
|
||||
/// </summary>
|
||||
/// <param name="data">The notification body.</param>
|
||||
/// <returns>The string message body.</returns>
|
||||
public string GetMessageBody(Dictionary<string, object> data)
|
||||
{
|
||||
return SendAllProperties
|
||||
? JsonSerializer.Serialize(data, JsonDefaults.Options)
|
||||
: GetCompiledTemplate()(data);
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the message body.
|
||||
/// </summary>
|
||||
/// <param name="data">The notification body.</param>
|
||||
/// <returns>The string message body.</returns>
|
||||
public string GetMessageBody(Dictionary<string, object> data)
|
||||
{
|
||||
return SendAllProperties
|
||||
? JsonSerializer.Serialize(data, JsonDefaults.Options)
|
||||
: GetCompiledTemplate()(data);
|
||||
}
|
||||
}
|
||||
|
@ -9,88 +9,87 @@ using Jellyfin.Plugin.Webhook.Extensions;
|
||||
using MediaBrowser.Common.Net;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Discord
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Discord;
|
||||
|
||||
/// <summary>
|
||||
/// Client for the <see cref="DiscordOption"/>.
|
||||
/// </summary>
|
||||
public class DiscordClient : BaseClient, IWebhookClient<DiscordOption>
|
||||
{
|
||||
private readonly ILogger<DiscordClient> _logger;
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
|
||||
/// <summary>
|
||||
/// Client for the <see cref="DiscordOption"/>.
|
||||
/// Initializes a new instance of the <see cref="DiscordClient"/> class.
|
||||
/// </summary>
|
||||
public class DiscordClient : BaseClient, IWebhookClient<DiscordOption>
|
||||
/// <param name="logger">Instance of the <see cref="ILogger{DiscordDestination}"/> interface.</param>
|
||||
/// <param name="httpClientFactory">Instance of the<see cref="IHttpClientFactory"/> interface.</param>
|
||||
public DiscordClient(ILogger<DiscordClient> logger, IHttpClientFactory httpClientFactory)
|
||||
{
|
||||
private readonly ILogger<DiscordClient> _logger;
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
_logger = logger;
|
||||
_httpClientFactory = httpClientFactory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DiscordClient"/> class.
|
||||
/// </summary>
|
||||
/// <param name="logger">Instance of the <see cref="ILogger{DiscordDestination}"/> interface.</param>
|
||||
/// <param name="httpClientFactory">Instance of the<see cref="IHttpClientFactory"/> interface.</param>
|
||||
public DiscordClient(ILogger<DiscordClient> logger, IHttpClientFactory httpClientFactory)
|
||||
/// <inheritdoc />
|
||||
public async Task SendAsync(DiscordOption option, Dictionary<string, object> data)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = logger;
|
||||
_httpClientFactory = httpClientFactory;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task SendAsync(DiscordOption option, Dictionary<string, object> data)
|
||||
{
|
||||
try
|
||||
if (string.IsNullOrEmpty(option.WebhookUri))
|
||||
{
|
||||
if (string.IsNullOrEmpty(option.WebhookUri))
|
||||
{
|
||||
throw new ArgumentException(nameof(option.WebhookUri));
|
||||
}
|
||||
|
||||
if (!SendWebhook(_logger, option, data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Add discord specific properties.
|
||||
data["MentionType"] = GetMentionType(option.MentionType);
|
||||
if (!string.IsNullOrEmpty(option.EmbedColor))
|
||||
{
|
||||
data["EmbedColor"] = FormatColorCode(option.EmbedColor);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(option.AvatarUrl))
|
||||
{
|
||||
data["AvatarUrl"] = option.AvatarUrl;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(option.Username))
|
||||
{
|
||||
data["Username"] = option.Username;
|
||||
data["BotUsername"] = option.Username;
|
||||
}
|
||||
|
||||
var body = option.GetMessageBody(data);
|
||||
_logger.LogDebug("SendAsync Body: {@Body}", body);
|
||||
using var content = new StringContent(body, Encoding.UTF8, MediaTypeNames.Application.Json);
|
||||
using var response = await _httpClientFactory
|
||||
.CreateClient(NamedClient.Default)
|
||||
.PostAsync(new Uri(option.WebhookUri), content)
|
||||
.ConfigureAwait(false);
|
||||
await response.LogIfFailedAsync(_logger).ConfigureAwait(false);
|
||||
throw new ArgumentException(nameof(option.WebhookUri));
|
||||
}
|
||||
catch (HttpRequestException e)
|
||||
|
||||
if (!SendWebhook(_logger, option, data))
|
||||
{
|
||||
_logger.LogWarning(e, "Error sending notification");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private static int FormatColorCode(string hexCode)
|
||||
{
|
||||
return int.Parse(hexCode[1..6], NumberStyles.HexNumber, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
private static string GetMentionType(DiscordMentionType mentionType)
|
||||
{
|
||||
return mentionType switch
|
||||
// Add discord specific properties.
|
||||
data["MentionType"] = GetMentionType(option.MentionType);
|
||||
if (!string.IsNullOrEmpty(option.EmbedColor))
|
||||
{
|
||||
DiscordMentionType.Everyone => "@everyone",
|
||||
DiscordMentionType.Here => "@here",
|
||||
_ => string.Empty
|
||||
};
|
||||
data["EmbedColor"] = FormatColorCode(option.EmbedColor);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(option.AvatarUrl))
|
||||
{
|
||||
data["AvatarUrl"] = option.AvatarUrl;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(option.Username))
|
||||
{
|
||||
data["Username"] = option.Username;
|
||||
data["BotUsername"] = option.Username;
|
||||
}
|
||||
|
||||
var body = option.GetMessageBody(data);
|
||||
_logger.LogDebug("SendAsync Body: {@Body}", body);
|
||||
using var content = new StringContent(body, Encoding.UTF8, MediaTypeNames.Application.Json);
|
||||
using var response = await _httpClientFactory
|
||||
.CreateClient(NamedClient.Default)
|
||||
.PostAsync(new Uri(option.WebhookUri), content)
|
||||
.ConfigureAwait(false);
|
||||
await response.LogIfFailedAsync(_logger).ConfigureAwait(false);
|
||||
}
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
_logger.LogWarning(e, "Error sending notification");
|
||||
}
|
||||
}
|
||||
|
||||
private static int FormatColorCode(string hexCode)
|
||||
{
|
||||
return int.Parse(hexCode[1..6], NumberStyles.HexNumber, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
private static string GetMentionType(DiscordMentionType mentionType)
|
||||
{
|
||||
return mentionType switch
|
||||
{
|
||||
DiscordMentionType.Everyone => "@everyone",
|
||||
DiscordMentionType.Here => "@here",
|
||||
_ => string.Empty
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +1,22 @@
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Discord
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Discord;
|
||||
|
||||
/// <summary>
|
||||
/// Discord mention type.
|
||||
/// </summary>
|
||||
public enum DiscordMentionType
|
||||
{
|
||||
/// <summary>
|
||||
/// Discord mention type.
|
||||
/// Mention @everyone.
|
||||
/// </summary>
|
||||
public enum DiscordMentionType
|
||||
{
|
||||
/// <summary>
|
||||
/// Mention @everyone.
|
||||
/// </summary>
|
||||
Everyone = 2,
|
||||
Everyone = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Mention @here.
|
||||
/// </summary>
|
||||
Here = 1,
|
||||
/// <summary>
|
||||
/// Mention @here.
|
||||
/// </summary>
|
||||
Here = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Mention none.
|
||||
/// </summary>
|
||||
None = 0
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Mention none.
|
||||
/// </summary>
|
||||
None = 0
|
||||
}
|
||||
|
@ -1,28 +1,27 @@
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Discord
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Discord;
|
||||
|
||||
/// <summary>
|
||||
/// Discord specific options.
|
||||
/// </summary>
|
||||
public class DiscordOption : BaseOption
|
||||
{
|
||||
/// <summary>
|
||||
/// Discord specific options.
|
||||
/// Gets or sets the embed color.
|
||||
/// </summary>
|
||||
public class DiscordOption : BaseOption
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the embed color.
|
||||
/// </summary>
|
||||
public string? EmbedColor { get; set; }
|
||||
public string? EmbedColor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the avatar url.
|
||||
/// </summary>
|
||||
public string? AvatarUrl { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the avatar url.
|
||||
/// </summary>
|
||||
public string? AvatarUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the bot username.
|
||||
/// </summary>
|
||||
public string? Username { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the bot username.
|
||||
/// </summary>
|
||||
public string? Username { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the mention type.
|
||||
/// </summary>
|
||||
public DiscordMentionType MentionType { get; set; }
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the mention type.
|
||||
/// </summary>
|
||||
public DiscordMentionType MentionType { get; set; }
|
||||
}
|
||||
|
@ -9,83 +9,82 @@ using MediaBrowser.Common.Net;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Generic
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// Client for the <see cref="GenericOption"/>.
|
||||
/// </summary>
|
||||
public class GenericClient : BaseClient, IWebhookClient<GenericOption>
|
||||
{
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly ILogger<GenericClient> _logger;
|
||||
|
||||
/// <summary>
|
||||
/// Client for the <see cref="GenericOption"/>.
|
||||
/// Initializes a new instance of the <see cref="GenericClient"/> class.
|
||||
/// </summary>
|
||||
public class GenericClient : BaseClient, IWebhookClient<GenericOption>
|
||||
/// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/>.</param>
|
||||
/// <param name="logger">Instance of the <see cref="ILogger{GenericClient}"/> interface.</param>
|
||||
public GenericClient(
|
||||
IHttpClientFactory httpClientFactory,
|
||||
ILogger<GenericClient> logger)
|
||||
{
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly ILogger<GenericClient> _logger;
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GenericClient"/> class.
|
||||
/// </summary>
|
||||
/// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/>.</param>
|
||||
/// <param name="logger">Instance of the <see cref="ILogger{GenericClient}"/> interface.</param>
|
||||
public GenericClient(
|
||||
IHttpClientFactory httpClientFactory,
|
||||
ILogger<GenericClient> logger)
|
||||
/// <inheritdoc />
|
||||
public async Task SendAsync(GenericOption option, Dictionary<string, object> data)
|
||||
{
|
||||
try
|
||||
{
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_logger = logger;
|
||||
if (!SendWebhook(_logger, option, data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var field in option.Fields)
|
||||
{
|
||||
if (string.IsNullOrEmpty(field.Key) || string.IsNullOrEmpty(field.Value))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
data[field.Key] = field.Value;
|
||||
}
|
||||
|
||||
var body = option.GetMessageBody(data);
|
||||
_logger.LogDebug("SendAsync Body: {@Body}", body);
|
||||
using var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, option.WebhookUri);
|
||||
var contentType = MediaTypeNames.Text.Plain;
|
||||
foreach (var header in option.Headers)
|
||||
{
|
||||
if (string.IsNullOrEmpty(header.Key) || string.IsNullOrEmpty(header.Value))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Content-Type cannot be set manually, must be set on the content.
|
||||
if (string.Equals(HeaderNames.ContentType, header.Key, StringComparison.OrdinalIgnoreCase)
|
||||
&& !string.IsNullOrEmpty(header.Value))
|
||||
{
|
||||
contentType = header.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
httpRequestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value);
|
||||
}
|
||||
}
|
||||
|
||||
httpRequestMessage.Content = new StringContent(body, Encoding.UTF8, contentType);
|
||||
using var response = await _httpClientFactory
|
||||
.CreateClient(NamedClient.Default)
|
||||
.SendAsync(httpRequestMessage)
|
||||
.ConfigureAwait(false);
|
||||
await response.LogIfFailedAsync(_logger).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task SendAsync(GenericOption option, Dictionary<string, object> data)
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!SendWebhook(_logger, option, data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var field in option.Fields)
|
||||
{
|
||||
if (string.IsNullOrEmpty(field.Key) || string.IsNullOrEmpty(field.Value))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
data[field.Key] = field.Value;
|
||||
}
|
||||
|
||||
var body = option.GetMessageBody(data);
|
||||
_logger.LogDebug("SendAsync Body: {@Body}", body);
|
||||
using var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, option.WebhookUri);
|
||||
var contentType = MediaTypeNames.Text.Plain;
|
||||
foreach (var header in option.Headers)
|
||||
{
|
||||
if (string.IsNullOrEmpty(header.Key) || string.IsNullOrEmpty(header.Value))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Content-Type cannot be set manually, must be set on the content.
|
||||
if (string.Equals(HeaderNames.ContentType, header.Key, StringComparison.OrdinalIgnoreCase)
|
||||
&& !string.IsNullOrEmpty(header.Value))
|
||||
{
|
||||
contentType = header.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
httpRequestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value);
|
||||
}
|
||||
}
|
||||
|
||||
httpRequestMessage.Content = new StringContent(body, Encoding.UTF8, contentType);
|
||||
using var response = await _httpClientFactory
|
||||
.CreateClient(NamedClient.Default)
|
||||
.SendAsync(httpRequestMessage)
|
||||
.ConfigureAwait(false);
|
||||
await response.LogIfFailedAsync(_logger).ConfigureAwait(false);
|
||||
}
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
_logger.LogWarning(e, "Error sending notification");
|
||||
}
|
||||
_logger.LogWarning(e, "Error sending notification");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,29 +1,28 @@
|
||||
using System;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Generic
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// Generic webhook options.
|
||||
/// </summary>
|
||||
public class GenericOption : BaseOption
|
||||
{
|
||||
/// <summary>
|
||||
/// Generic webhook options.
|
||||
/// Initializes a new instance of the <see cref="GenericOption"/> class.
|
||||
/// </summary>
|
||||
public class GenericOption : BaseOption
|
||||
public GenericOption()
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GenericOption"/> class.
|
||||
/// </summary>
|
||||
public GenericOption()
|
||||
{
|
||||
Headers = Array.Empty<GenericOptionValue>();
|
||||
Fields = Array.Empty<GenericOptionValue>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the headers.
|
||||
/// </summary>
|
||||
public GenericOptionValue[] Headers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the fields.
|
||||
/// </summary>
|
||||
public GenericOptionValue[] Fields { get; set; }
|
||||
Headers = Array.Empty<GenericOptionValue>();
|
||||
Fields = Array.Empty<GenericOptionValue>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the headers.
|
||||
/// </summary>
|
||||
public GenericOptionValue[] Headers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the fields.
|
||||
/// </summary>
|
||||
public GenericOptionValue[] Fields { get; set; }
|
||||
}
|
||||
|
@ -1,18 +1,17 @@
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Generic
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// Generic option value.
|
||||
/// </summary>
|
||||
public class GenericOptionValue
|
||||
{
|
||||
/// <summary>
|
||||
/// Generic option value.
|
||||
/// Gets or sets the option key.
|
||||
/// </summary>
|
||||
public class GenericOptionValue
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the option key.
|
||||
/// </summary>
|
||||
public string Key { get; set; } = string.Empty;
|
||||
public string Key { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the option value.
|
||||
/// </summary>
|
||||
public string Value { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the option value.
|
||||
/// </summary>
|
||||
public string Value { get; set; } = string.Empty;
|
||||
}
|
||||
|
@ -6,80 +6,79 @@ using Jellyfin.Plugin.Webhook.Extensions;
|
||||
using MediaBrowser.Common.Net;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.GenericForm
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.GenericForm;
|
||||
|
||||
/// <summary>
|
||||
/// Client for the <see cref="GenericFormOption"/>.
|
||||
/// </summary>
|
||||
public class GenericFormClient : BaseClient, IWebhookClient<GenericFormOption>
|
||||
{
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly ILogger<GenericFormClient> _logger;
|
||||
|
||||
/// <summary>
|
||||
/// Client for the <see cref="GenericFormOption"/>.
|
||||
/// Initializes a new instance of the <see cref="GenericFormClient"/> class.
|
||||
/// </summary>
|
||||
public class GenericFormClient : BaseClient, IWebhookClient<GenericFormOption>
|
||||
/// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/>.</param>
|
||||
/// <param name="logger">Instance of the <see cref="ILogger{GenericFormClient}"/> interface.</param>
|
||||
public GenericFormClient(
|
||||
IHttpClientFactory httpClientFactory,
|
||||
ILogger<GenericFormClient> logger)
|
||||
{
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly ILogger<GenericFormClient> _logger;
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GenericFormClient"/> class.
|
||||
/// </summary>
|
||||
/// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/>.</param>
|
||||
/// <param name="logger">Instance of the <see cref="ILogger{GenericFormClient}"/> interface.</param>
|
||||
public GenericFormClient(
|
||||
IHttpClientFactory httpClientFactory,
|
||||
ILogger<GenericFormClient> logger)
|
||||
/// <inheritdoc />
|
||||
public async Task SendAsync(GenericFormOption option, Dictionary<string, object> data)
|
||||
{
|
||||
try
|
||||
{
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_logger = logger;
|
||||
if (!SendWebhook(_logger, option, data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var field in option.Fields)
|
||||
{
|
||||
if (string.IsNullOrEmpty(field.Key) || string.IsNullOrEmpty(field.Value))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
data[field.Key] = field.Value;
|
||||
}
|
||||
|
||||
var body = option.GetMessageBody(data);
|
||||
var dictionaryBody = JsonSerializer.Deserialize<Dictionary<string, string>>(body);
|
||||
if (dictionaryBody is null)
|
||||
{
|
||||
_logger.LogWarning("Body is null, unable to send webhook");
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.LogDebug("SendAsync Body: {@Body}", body);
|
||||
using var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, option.WebhookUri);
|
||||
foreach (var header in option.Headers)
|
||||
{
|
||||
if (string.IsNullOrEmpty(header.Key) || string.IsNullOrEmpty(header.Value))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
httpRequestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value);
|
||||
}
|
||||
|
||||
httpRequestMessage.Content = new FormUrlEncodedContent(dictionaryBody!);
|
||||
using var response = await _httpClientFactory
|
||||
.CreateClient(NamedClient.Default)
|
||||
.SendAsync(httpRequestMessage)
|
||||
.ConfigureAwait(false);
|
||||
await response.LogIfFailedAsync(_logger).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task SendAsync(GenericFormOption option, Dictionary<string, object> data)
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!SendWebhook(_logger, option, data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var field in option.Fields)
|
||||
{
|
||||
if (string.IsNullOrEmpty(field.Key) || string.IsNullOrEmpty(field.Value))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
data[field.Key] = field.Value;
|
||||
}
|
||||
|
||||
var body = option.GetMessageBody(data);
|
||||
var dictionaryBody = JsonSerializer.Deserialize<Dictionary<string, string>>(body);
|
||||
if (dictionaryBody is null)
|
||||
{
|
||||
_logger.LogWarning("Body is null, unable to send webhook");
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.LogDebug("SendAsync Body: {@Body}", body);
|
||||
using var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, option.WebhookUri);
|
||||
foreach (var header in option.Headers)
|
||||
{
|
||||
if (string.IsNullOrEmpty(header.Key) || string.IsNullOrEmpty(header.Value))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
httpRequestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value);
|
||||
}
|
||||
|
||||
httpRequestMessage.Content = new FormUrlEncodedContent(dictionaryBody!);
|
||||
using var response = await _httpClientFactory
|
||||
.CreateClient(NamedClient.Default)
|
||||
.SendAsync(httpRequestMessage)
|
||||
.ConfigureAwait(false);
|
||||
await response.LogIfFailedAsync(_logger).ConfigureAwait(false);
|
||||
}
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
_logger.LogWarning(e, "Error sending notification");
|
||||
}
|
||||
_logger.LogWarning(e, "Error sending notification");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,29 +1,28 @@
|
||||
using System;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.GenericForm
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.GenericForm;
|
||||
|
||||
/// <summary>
|
||||
/// Generic form webhook options.
|
||||
/// </summary>
|
||||
public class GenericFormOption : BaseOption
|
||||
{
|
||||
/// <summary>
|
||||
/// Generic form webhook options.
|
||||
/// Initializes a new instance of the <see cref="GenericFormOption"/> class.
|
||||
/// </summary>
|
||||
public class GenericFormOption : BaseOption
|
||||
public GenericFormOption()
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GenericFormOption"/> class.
|
||||
/// </summary>
|
||||
public GenericFormOption()
|
||||
{
|
||||
Headers = Array.Empty<GenericFormOptionValue>();
|
||||
Fields = Array.Empty<GenericFormOptionValue>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the headers.
|
||||
/// </summary>
|
||||
public GenericFormOptionValue[] Headers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the fields.
|
||||
/// </summary>
|
||||
public GenericFormOptionValue[] Fields { get; set; }
|
||||
Headers = Array.Empty<GenericFormOptionValue>();
|
||||
Fields = Array.Empty<GenericFormOptionValue>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the headers.
|
||||
/// </summary>
|
||||
public GenericFormOptionValue[] Headers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the fields.
|
||||
/// </summary>
|
||||
public GenericFormOptionValue[] Fields { get; set; }
|
||||
}
|
||||
|
@ -1,18 +1,17 @@
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.GenericForm
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.GenericForm;
|
||||
|
||||
/// <summary>
|
||||
/// Generic form option value.
|
||||
/// </summary>
|
||||
public class GenericFormOptionValue
|
||||
{
|
||||
/// <summary>
|
||||
/// Generic form option value.
|
||||
/// Gets or sets the option key.
|
||||
/// </summary>
|
||||
public class GenericFormOptionValue
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the option key.
|
||||
/// </summary>
|
||||
public string Key { get; set; } = string.Empty;
|
||||
public string Key { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the option value.
|
||||
/// </summary>
|
||||
public string Value { get; set; } = string.Empty;
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the option value.
|
||||
/// </summary>
|
||||
public string Value { get; set; } = string.Empty;
|
||||
}
|
||||
|
@ -8,58 +8,57 @@ using Jellyfin.Plugin.Webhook.Extensions;
|
||||
using MediaBrowser.Common.Net;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Gotify
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Gotify;
|
||||
|
||||
/// <summary>
|
||||
/// Client for the <see cref="GotifyOption"/>.
|
||||
/// </summary>
|
||||
public class GotifyClient : BaseClient, IWebhookClient<GotifyOption>
|
||||
{
|
||||
private readonly ILogger<GotifyClient> _logger;
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
|
||||
/// <summary>
|
||||
/// Client for the <see cref="GotifyOption"/>.
|
||||
/// Initializes a new instance of the <see cref="GotifyClient"/> class.
|
||||
/// </summary>
|
||||
public class GotifyClient : BaseClient, IWebhookClient<GotifyOption>
|
||||
/// <param name="logger">Instance of the <see cref="ILogger{GotifyDestination}"/> interface.</param>
|
||||
/// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/>.</param>
|
||||
public GotifyClient(ILogger<GotifyClient> logger, IHttpClientFactory httpClientFactory)
|
||||
{
|
||||
private readonly ILogger<GotifyClient> _logger;
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
_logger = logger;
|
||||
_httpClientFactory = httpClientFactory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GotifyClient"/> class.
|
||||
/// </summary>
|
||||
/// <param name="logger">Instance of the <see cref="ILogger{GotifyDestination}"/> interface.</param>
|
||||
/// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/>.</param>
|
||||
public GotifyClient(ILogger<GotifyClient> logger, IHttpClientFactory httpClientFactory)
|
||||
/// <inheritdoc />
|
||||
public async Task SendAsync(GotifyOption option, Dictionary<string, object> data)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = logger;
|
||||
_httpClientFactory = httpClientFactory;
|
||||
if (string.IsNullOrEmpty(option.WebhookUri))
|
||||
{
|
||||
throw new ArgumentException(nameof(option.WebhookUri));
|
||||
}
|
||||
|
||||
if (!SendWebhook(_logger, option, data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Add gotify specific properties.
|
||||
data["Priority"] = option.Priority;
|
||||
|
||||
var body = option.GetMessageBody(data);
|
||||
_logger.LogDebug("SendAsync Body: {@Body}", body);
|
||||
using var content = new StringContent(body, Encoding.UTF8, MediaTypeNames.Application.Json);
|
||||
using var response = await _httpClientFactory
|
||||
.CreateClient(NamedClient.Default)
|
||||
.PostAsync(new Uri(option.WebhookUri.TrimEnd() + $"/message?token={option.Token}"), content)
|
||||
.ConfigureAwait(false);
|
||||
await response.LogIfFailedAsync(_logger).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task SendAsync(GotifyOption option, Dictionary<string, object> data)
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(option.WebhookUri))
|
||||
{
|
||||
throw new ArgumentException(nameof(option.WebhookUri));
|
||||
}
|
||||
|
||||
if (!SendWebhook(_logger, option, data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Add gotify specific properties.
|
||||
data["Priority"] = option.Priority;
|
||||
|
||||
var body = option.GetMessageBody(data);
|
||||
_logger.LogDebug("SendAsync Body: {@Body}", body);
|
||||
using var content = new StringContent(body, Encoding.UTF8, MediaTypeNames.Application.Json);
|
||||
using var response = await _httpClientFactory
|
||||
.CreateClient(NamedClient.Default)
|
||||
.PostAsync(new Uri(option.WebhookUri.TrimEnd() + $"/message?token={option.Token}"), content)
|
||||
.ConfigureAwait(false);
|
||||
await response.LogIfFailedAsync(_logger).ConfigureAwait(false);
|
||||
}
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
_logger.LogWarning(e, "Error sending notification");
|
||||
}
|
||||
_logger.LogWarning(e, "Error sending notification");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,17 @@
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Gotify
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Gotify;
|
||||
|
||||
/// <summary>
|
||||
/// Gotify specific options.
|
||||
/// </summary>
|
||||
public class GotifyOption : BaseOption
|
||||
{
|
||||
/// <summary>
|
||||
/// Gotify specific options.
|
||||
/// Gets or sets the authentication token.
|
||||
/// </summary>
|
||||
public class GotifyOption : BaseOption
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the authentication token.
|
||||
/// </summary>
|
||||
public string? Token { get; set; }
|
||||
public string? Token { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the notification priority.
|
||||
/// </summary>
|
||||
public int Priority { get; set; }
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the notification priority.
|
||||
/// </summary>
|
||||
public int Priority { get; set; }
|
||||
}
|
||||
|
@ -1,21 +1,20 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations;
|
||||
|
||||
/// <summary>
|
||||
/// Destination interface.
|
||||
/// </summary>
|
||||
/// <typeparam name="TDestinationOption">The type of options.</typeparam>
|
||||
public interface IWebhookClient<in TDestinationOption>
|
||||
where TDestinationOption : BaseOption
|
||||
{
|
||||
/// <summary>
|
||||
/// Destination interface.
|
||||
/// Send message to destination.
|
||||
/// </summary>
|
||||
/// <typeparam name="TDestinationOption">The type of options.</typeparam>
|
||||
public interface IWebhookClient<in TDestinationOption>
|
||||
where TDestinationOption : BaseOption
|
||||
{
|
||||
/// <summary>
|
||||
/// Send message to destination.
|
||||
/// </summary>
|
||||
/// <param name="option">The destination option.</param>
|
||||
/// <param name="data">The message to send.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
Task SendAsync(TDestinationOption option, Dictionary<string, object> data);
|
||||
}
|
||||
/// <param name="option">The destination option.</param>
|
||||
/// <param name="data">The message to send.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
Task SendAsync(TDestinationOption option, Dictionary<string, object> data);
|
||||
}
|
||||
|
@ -22,4 +22,4 @@ public interface IMqttClients
|
||||
/// <param name="guid">guid of MqttOption.</param>
|
||||
/// <returns>Instance of the <see cref="IManagedMqttClient"/> interface.</returns>
|
||||
IManagedMqttClient? GetClient(Guid guid);
|
||||
}
|
||||
}
|
||||
|
@ -52,4 +52,4 @@ public class MqttClient : BaseClient, IWebhookClient<MqttOption>
|
||||
_logger.LogDebug(e, "Error sending MQTT notification");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -131,4 +131,4 @@ public class MqttClients : IMqttClients, IDisposable
|
||||
client.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -70,4 +70,4 @@ public class MqttOption : BaseOption
|
||||
/// </summary>
|
||||
/// <returns>The compiled handlebars subject template.</returns>
|
||||
public HandlebarsTemplate<object, string> GetCompiledTopicTemplate() => _compiledTopicTemplate ??= Handlebars.Compile(HandlebarsFunctionHelpers.Base64Decode(Topic));
|
||||
}
|
||||
}
|
||||
|
@ -1,128 +1,127 @@
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations;
|
||||
|
||||
/// <summary>
|
||||
/// The type of notification.
|
||||
/// </summary>
|
||||
public enum NotificationType
|
||||
{
|
||||
/// <summary>
|
||||
/// The type of notification.
|
||||
/// No notification type.
|
||||
/// </summary>
|
||||
public enum NotificationType
|
||||
{
|
||||
/// <summary>
|
||||
/// No notification type.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Item added notification.
|
||||
/// </summary>
|
||||
ItemAdded = 1,
|
||||
/// <summary>
|
||||
/// Item added notification.
|
||||
/// </summary>
|
||||
ItemAdded = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Generic notification.
|
||||
/// </summary>
|
||||
Generic = 2,
|
||||
/// <summary>
|
||||
/// Generic notification.
|
||||
/// </summary>
|
||||
Generic = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Playback start notification.
|
||||
/// </summary>
|
||||
PlaybackStart = 3,
|
||||
/// <summary>
|
||||
/// Playback start notification.
|
||||
/// </summary>
|
||||
PlaybackStart = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Playback progress notification.
|
||||
/// </summary>
|
||||
PlaybackProgress = 4,
|
||||
/// <summary>
|
||||
/// Playback progress notification.
|
||||
/// </summary>
|
||||
PlaybackProgress = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Playback stop notification.
|
||||
/// </summary>
|
||||
PlaybackStop = 5,
|
||||
/// <summary>
|
||||
/// Playback stop notification.
|
||||
/// </summary>
|
||||
PlaybackStop = 5,
|
||||
|
||||
/// <summary>
|
||||
/// Subtitle download failure.
|
||||
/// </summary>
|
||||
SubtitleDownloadFailure = 6,
|
||||
/// <summary>
|
||||
/// Subtitle download failure.
|
||||
/// </summary>
|
||||
SubtitleDownloadFailure = 6,
|
||||
|
||||
/// <summary>
|
||||
/// Authentication failure.
|
||||
/// </summary>
|
||||
AuthenticationFailure = 7,
|
||||
/// <summary>
|
||||
/// Authentication failure.
|
||||
/// </summary>
|
||||
AuthenticationFailure = 7,
|
||||
|
||||
/// <summary>
|
||||
/// Authentication success.
|
||||
/// </summary>
|
||||
AuthenticationSuccess = 8,
|
||||
/// <summary>
|
||||
/// Authentication success.
|
||||
/// </summary>
|
||||
AuthenticationSuccess = 8,
|
||||
|
||||
/// <summary>
|
||||
/// Session started.
|
||||
/// </summary>
|
||||
SessionStart = 9,
|
||||
/// <summary>
|
||||
/// Session started.
|
||||
/// </summary>
|
||||
SessionStart = 9,
|
||||
|
||||
/// <summary>
|
||||
/// Server pending restart.
|
||||
/// </summary>
|
||||
PendingRestart = 10,
|
||||
/// <summary>
|
||||
/// Server pending restart.
|
||||
/// </summary>
|
||||
PendingRestart = 10,
|
||||
|
||||
/// <summary>
|
||||
/// Task completed.
|
||||
/// </summary>
|
||||
TaskCompleted = 11,
|
||||
/// <summary>
|
||||
/// Task completed.
|
||||
/// </summary>
|
||||
TaskCompleted = 11,
|
||||
|
||||
/// <summary>
|
||||
/// Plugin installation cancelled.
|
||||
/// </summary>
|
||||
PluginInstallationCancelled = 12,
|
||||
/// <summary>
|
||||
/// Plugin installation cancelled.
|
||||
/// </summary>
|
||||
PluginInstallationCancelled = 12,
|
||||
|
||||
/// <summary>
|
||||
/// Plugin installation failed.
|
||||
/// </summary>
|
||||
PluginInstallationFailed = 13,
|
||||
/// <summary>
|
||||
/// Plugin installation failed.
|
||||
/// </summary>
|
||||
PluginInstallationFailed = 13,
|
||||
|
||||
/// <summary>
|
||||
/// Plugin installed.
|
||||
/// </summary>
|
||||
PluginInstalled = 14,
|
||||
/// <summary>
|
||||
/// Plugin installed.
|
||||
/// </summary>
|
||||
PluginInstalled = 14,
|
||||
|
||||
/// <summary>
|
||||
/// Plugin installing.
|
||||
/// </summary>
|
||||
PluginInstalling = 15,
|
||||
/// <summary>
|
||||
/// Plugin installing.
|
||||
/// </summary>
|
||||
PluginInstalling = 15,
|
||||
|
||||
/// <summary>
|
||||
/// Plugin uninstalled.
|
||||
/// </summary>
|
||||
PluginUninstalled = 16,
|
||||
/// <summary>
|
||||
/// Plugin uninstalled.
|
||||
/// </summary>
|
||||
PluginUninstalled = 16,
|
||||
|
||||
/// <summary>
|
||||
/// Plugin updated.
|
||||
/// </summary>
|
||||
PluginUpdated = 17,
|
||||
/// <summary>
|
||||
/// Plugin updated.
|
||||
/// </summary>
|
||||
PluginUpdated = 17,
|
||||
|
||||
/// <summary>
|
||||
/// User created.
|
||||
/// </summary>
|
||||
UserCreated = 18,
|
||||
/// <summary>
|
||||
/// User created.
|
||||
/// </summary>
|
||||
UserCreated = 18,
|
||||
|
||||
/// <summary>
|
||||
/// User created.
|
||||
/// </summary>
|
||||
UserDeleted = 19,
|
||||
/// <summary>
|
||||
/// User created.
|
||||
/// </summary>
|
||||
UserDeleted = 19,
|
||||
|
||||
/// <summary>
|
||||
/// User locked out.
|
||||
/// </summary>
|
||||
UserLockedOut = 20,
|
||||
/// <summary>
|
||||
/// User locked out.
|
||||
/// </summary>
|
||||
UserLockedOut = 20,
|
||||
|
||||
/// <summary>
|
||||
/// User password changed.
|
||||
/// </summary>
|
||||
UserPasswordChanged = 21,
|
||||
/// <summary>
|
||||
/// User password changed.
|
||||
/// </summary>
|
||||
UserPasswordChanged = 21,
|
||||
|
||||
/// <summary>
|
||||
/// User updated.
|
||||
/// </summary>
|
||||
UserUpdated = 22,
|
||||
/// <summary>
|
||||
/// User updated.
|
||||
/// </summary>
|
||||
UserUpdated = 22,
|
||||
|
||||
/// <summary>
|
||||
/// User data saved.
|
||||
/// </summary>
|
||||
UserDataSaved = 23
|
||||
}
|
||||
/// <summary>
|
||||
/// User data saved.
|
||||
/// </summary>
|
||||
UserDataSaved = 23
|
||||
}
|
||||
|
@ -7,60 +7,59 @@ using Jellyfin.Plugin.Webhook.Extensions;
|
||||
using MediaBrowser.Common.Net;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Pushbullet
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Pushbullet;
|
||||
|
||||
/// <summary>
|
||||
/// Client for the <see cref="PushbulletOption"/>.
|
||||
/// </summary>
|
||||
public class PushbulletClient : BaseClient, IWebhookClient<PushbulletOption>
|
||||
{
|
||||
private readonly ILogger<PushbulletClient> _logger;
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
|
||||
/// <summary>
|
||||
/// Client for the <see cref="PushbulletOption"/>.
|
||||
/// Initializes a new instance of the <see cref="PushbulletClient"/> class.
|
||||
/// </summary>
|
||||
public class PushbulletClient : BaseClient, IWebhookClient<PushbulletOption>
|
||||
/// <param name="logger">Instance of the <see cref="ILogger{PushbulletClient}"/> interface.</param>
|
||||
/// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/> interface.</param>
|
||||
public PushbulletClient(
|
||||
ILogger<PushbulletClient> logger,
|
||||
IHttpClientFactory httpClientFactory)
|
||||
{
|
||||
private readonly ILogger<PushbulletClient> _logger;
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
_logger = logger;
|
||||
_httpClientFactory = httpClientFactory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PushbulletClient"/> class.
|
||||
/// </summary>
|
||||
/// <param name="logger">Instance of the <see cref="ILogger{PushbulletClient}"/> interface.</param>
|
||||
/// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/> interface.</param>
|
||||
public PushbulletClient(
|
||||
ILogger<PushbulletClient> logger,
|
||||
IHttpClientFactory httpClientFactory)
|
||||
/// <inheritdoc />
|
||||
public async Task SendAsync(PushbulletOption option, Dictionary<string, object> data)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = logger;
|
||||
_httpClientFactory = httpClientFactory;
|
||||
if (!SendWebhook(_logger, option, data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
data["PushbulletToken"] = option.Token;
|
||||
data["PushbulletDeviceId"] = option.DeviceId;
|
||||
data["PushbulletChannel"] = option.Channel;
|
||||
|
||||
var body = option.GetMessageBody(data);
|
||||
_logger.LogDebug("SendAsync Body: {@Body}", body);
|
||||
|
||||
using var requestOptions = new HttpRequestMessage(HttpMethod.Post, string.IsNullOrEmpty(option.WebhookUri) ? PushbulletOption.ApiUrl : option.WebhookUri);
|
||||
requestOptions.Headers.TryAddWithoutValidation("Access-Token", option.Token);
|
||||
requestOptions.Content = new StringContent(body, Encoding.UTF8, MediaTypeNames.Application.Json);
|
||||
|
||||
using var response = await _httpClientFactory
|
||||
.CreateClient(NamedClient.Default)
|
||||
.SendAsync(requestOptions)
|
||||
.ConfigureAwait(false);
|
||||
await response.LogIfFailedAsync(_logger).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task SendAsync(PushbulletOption option, Dictionary<string, object> data)
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!SendWebhook(_logger, option, data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
data["PushbulletToken"] = option.Token;
|
||||
data["PushbulletDeviceId"] = option.DeviceId;
|
||||
data["PushbulletChannel"] = option.Channel;
|
||||
|
||||
var body = option.GetMessageBody(data);
|
||||
_logger.LogDebug("SendAsync Body: {@Body}", body);
|
||||
|
||||
using var requestOptions = new HttpRequestMessage(HttpMethod.Post, string.IsNullOrEmpty(option.WebhookUri) ? PushbulletOption.ApiUrl : option.WebhookUri);
|
||||
requestOptions.Headers.TryAddWithoutValidation("Access-Token", option.Token);
|
||||
requestOptions.Content = new StringContent(body, Encoding.UTF8, MediaTypeNames.Application.Json);
|
||||
|
||||
using var response = await _httpClientFactory
|
||||
.CreateClient(NamedClient.Default)
|
||||
.SendAsync(requestOptions)
|
||||
.ConfigureAwait(false);
|
||||
await response.LogIfFailedAsync(_logger).ConfigureAwait(false);
|
||||
}
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
_logger.LogWarning(e, "Error sending notification");
|
||||
}
|
||||
_logger.LogWarning(e, "Error sending notification");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,31 +1,30 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Pushbullet
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Pushbullet;
|
||||
|
||||
/// <summary>
|
||||
/// Pushbullet specific option.
|
||||
/// </summary>
|
||||
public class PushbulletOption : BaseOption
|
||||
{
|
||||
/// <summary>
|
||||
/// Pushbullet specific option.
|
||||
/// The webhook endpoint.
|
||||
/// </summary>
|
||||
public class PushbulletOption : BaseOption
|
||||
{
|
||||
/// <summary>
|
||||
/// The webhook endpoint.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public const string ApiUrl = "https://api.pushbullet.com/v2/pushes";
|
||||
[JsonIgnore]
|
||||
public const string ApiUrl = "https://api.pushbullet.com/v2/pushes";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pushbullet token.
|
||||
/// </summary>
|
||||
public string Token { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// Gets or sets the pushbullet token.
|
||||
/// </summary>
|
||||
public string Token { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the device id.
|
||||
/// </summary>
|
||||
public string DeviceId { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// Gets or sets the device id.
|
||||
/// </summary>
|
||||
public string DeviceId { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the channel.
|
||||
/// </summary>
|
||||
public string Channel { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the channel.
|
||||
/// </summary>
|
||||
public string Channel { get; set; } = string.Empty;
|
||||
}
|
||||
|
@ -8,82 +8,81 @@ using Jellyfin.Plugin.Webhook.Extensions;
|
||||
using MediaBrowser.Common.Net;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Pushover
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Pushover;
|
||||
|
||||
/// <summary>
|
||||
/// Client for the <see cref="PushoverOption"/>.
|
||||
/// </summary>
|
||||
public class PushoverClient : BaseClient, IWebhookClient<PushoverOption>
|
||||
{
|
||||
private readonly ILogger<PushoverClient> _logger;
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
|
||||
/// <summary>
|
||||
/// Client for the <see cref="PushoverOption"/>.
|
||||
/// Initializes a new instance of the <see cref="PushoverClient"/> class.
|
||||
/// </summary>
|
||||
public class PushoverClient : BaseClient, IWebhookClient<PushoverOption>
|
||||
/// <param name="logger">Instance of the <see cref="ILogger{PushoverClient}"/> interface.</param>
|
||||
/// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/>.</param>
|
||||
public PushoverClient(ILogger<PushoverClient> logger, IHttpClientFactory httpClientFactory)
|
||||
{
|
||||
private readonly ILogger<PushoverClient> _logger;
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
_logger = logger;
|
||||
_httpClientFactory = httpClientFactory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PushoverClient"/> class.
|
||||
/// </summary>
|
||||
/// <param name="logger">Instance of the <see cref="ILogger{PushoverClient}"/> interface.</param>
|
||||
/// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/>.</param>
|
||||
public PushoverClient(ILogger<PushoverClient> logger, IHttpClientFactory httpClientFactory)
|
||||
/// <inheritdoc />
|
||||
public async Task SendAsync(PushoverOption option, Dictionary<string, object> data)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = logger;
|
||||
_httpClientFactory = httpClientFactory;
|
||||
if (!SendWebhook(_logger, option, data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
data["Token"] = option.Token;
|
||||
data["UserToken"] = option.UserToken;
|
||||
if (!string.IsNullOrEmpty(option.Device))
|
||||
{
|
||||
data["Device"] = option.Device;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(option.Title))
|
||||
{
|
||||
data["Title"] = option.Title;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(option.MessageUrl))
|
||||
{
|
||||
data["MessageUrl"] = option.MessageUrl;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(option.MessageUrlTitle))
|
||||
{
|
||||
data["MessageUrlTitle"] = option.MessageUrlTitle;
|
||||
}
|
||||
|
||||
if (option.MessagePriority is not null)
|
||||
{
|
||||
data["MessagePriority"] = option.MessagePriority;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(option.NotificationSound))
|
||||
{
|
||||
data["NotificationSound"] = option.NotificationSound;
|
||||
}
|
||||
|
||||
var body = option.GetMessageBody(data);
|
||||
_logger.LogDebug("SendAsync Body: {@Body}", body);
|
||||
using var content = new StringContent(body, Encoding.UTF8, MediaTypeNames.Application.Json);
|
||||
using var response = await _httpClientFactory
|
||||
.CreateClient(NamedClient.Default)
|
||||
.PostAsync(string.IsNullOrEmpty(option.WebhookUri) ? PushoverOption.ApiUrl : new Uri(option.WebhookUri), content)
|
||||
.ConfigureAwait(false);
|
||||
await response.LogIfFailedAsync(_logger).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task SendAsync(PushoverOption option, Dictionary<string, object> data)
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!SendWebhook(_logger, option, data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
data["Token"] = option.Token;
|
||||
data["UserToken"] = option.UserToken;
|
||||
if (!string.IsNullOrEmpty(option.Device))
|
||||
{
|
||||
data["Device"] = option.Device;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(option.Title))
|
||||
{
|
||||
data["Title"] = option.Title;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(option.MessageUrl))
|
||||
{
|
||||
data["MessageUrl"] = option.MessageUrl;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(option.MessageUrlTitle))
|
||||
{
|
||||
data["MessageUrlTitle"] = option.MessageUrlTitle;
|
||||
}
|
||||
|
||||
if (option.MessagePriority is not null)
|
||||
{
|
||||
data["MessagePriority"] = option.MessagePriority;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(option.NotificationSound))
|
||||
{
|
||||
data["NotificationSound"] = option.NotificationSound;
|
||||
}
|
||||
|
||||
var body = option.GetMessageBody(data);
|
||||
_logger.LogDebug("SendAsync Body: {@Body}", body);
|
||||
using var content = new StringContent(body, Encoding.UTF8, MediaTypeNames.Application.Json);
|
||||
using var response = await _httpClientFactory
|
||||
.CreateClient(NamedClient.Default)
|
||||
.PostAsync(string.IsNullOrEmpty(option.WebhookUri) ? PushoverOption.ApiUrl : new Uri(option.WebhookUri), content)
|
||||
.ConfigureAwait(false);
|
||||
await response.LogIfFailedAsync(_logger).ConfigureAwait(false);
|
||||
}
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
_logger.LogWarning(e, "Error sending notification");
|
||||
}
|
||||
_logger.LogWarning(e, "Error sending notification");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,57 +1,56 @@
|
||||
using System;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Pushover
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Pushover;
|
||||
|
||||
/// <summary>
|
||||
/// Pushover specific options.
|
||||
/// </summary>
|
||||
public class PushoverOption : BaseOption
|
||||
{
|
||||
/// <summary>
|
||||
/// Pushover specific options.
|
||||
/// The webhook endpoint.
|
||||
/// </summary>
|
||||
public class PushoverOption : BaseOption
|
||||
{
|
||||
/// <summary>
|
||||
/// The webhook endpoint.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public static readonly Uri ApiUrl = new Uri("https://api.pushover.net/1/messages.json");
|
||||
[JsonIgnore]
|
||||
public static readonly Uri ApiUrl = new Uri("https://api.pushover.net/1/messages.json");
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pushover token.
|
||||
/// </summary>
|
||||
public string Token { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// Gets or sets the pushover token.
|
||||
/// </summary>
|
||||
public string Token { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pushover user token.
|
||||
/// </summary>
|
||||
public string UserToken { get; set; } = string.Empty;
|
||||
/// <summary>
|
||||
/// Gets or sets the pushover user token.
|
||||
/// </summary>
|
||||
public string UserToken { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the device.
|
||||
/// </summary>
|
||||
public string? Device { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the device.
|
||||
/// </summary>
|
||||
public string? Device { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the message title.
|
||||
/// </summary>
|
||||
public string? Title { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the message title.
|
||||
/// </summary>
|
||||
public string? Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the message url.
|
||||
/// </summary>
|
||||
public string? MessageUrl { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the message url.
|
||||
/// </summary>
|
||||
public string? MessageUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the message url title.
|
||||
/// </summary>
|
||||
public string? MessageUrlTitle { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the message url title.
|
||||
/// </summary>
|
||||
public string? MessageUrlTitle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the message priority.
|
||||
/// </summary>
|
||||
public int? MessagePriority { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the message priority.
|
||||
/// </summary>
|
||||
public int? MessagePriority { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the notification sound.
|
||||
/// </summary>
|
||||
public string? NotificationSound { get; set; }
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the notification sound.
|
||||
/// </summary>
|
||||
public string? NotificationSound { get; set; }
|
||||
}
|
||||
|
@ -8,59 +8,58 @@ using Jellyfin.Plugin.Webhook.Extensions;
|
||||
using MediaBrowser.Common.Net;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Slack
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Slack;
|
||||
|
||||
/// <summary>
|
||||
/// Client for the <see cref="SlackOption"/>.
|
||||
/// </summary>
|
||||
public class SlackClient : BaseClient, IWebhookClient<SlackOption>
|
||||
{
|
||||
private readonly ILogger<SlackClient> _logger;
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
|
||||
/// <summary>
|
||||
/// Client for the <see cref="SlackOption"/>.
|
||||
/// Initializes a new instance of the <see cref="SlackClient"/> class.
|
||||
/// </summary>
|
||||
public class SlackClient : BaseClient, IWebhookClient<SlackOption>
|
||||
/// <param name="logger">Instance of the <see cref="ILogger{SlackClient}"/> interface.</param>
|
||||
/// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/>.</param>
|
||||
public SlackClient(ILogger<SlackClient> logger, IHttpClientFactory httpClientFactory)
|
||||
{
|
||||
private readonly ILogger<SlackClient> _logger;
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
_logger = logger;
|
||||
_httpClientFactory = httpClientFactory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SlackClient"/> class.
|
||||
/// </summary>
|
||||
/// <param name="logger">Instance of the <see cref="ILogger{SlackClient}"/> interface.</param>
|
||||
/// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/>.</param>
|
||||
public SlackClient(ILogger<SlackClient> logger, IHttpClientFactory httpClientFactory)
|
||||
/// <inheritdoc />
|
||||
public async Task SendAsync(SlackOption option, Dictionary<string, object> data)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = logger;
|
||||
_httpClientFactory = httpClientFactory;
|
||||
if (string.IsNullOrEmpty(option.WebhookUri))
|
||||
{
|
||||
throw new ArgumentException(nameof(option.WebhookUri));
|
||||
}
|
||||
|
||||
if (!SendWebhook(_logger, option, data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
data["SlackUsername"] = option.Username;
|
||||
data["BotUsername"] = option.Username;
|
||||
data["SlackIconUrl"] = option.IconUrl;
|
||||
|
||||
var body = option.GetMessageBody(data);
|
||||
_logger.LogDebug("SendAsync Body: {@Body}", body);
|
||||
using var content = new StringContent(body, Encoding.UTF8, MediaTypeNames.Application.Json);
|
||||
using var response = await _httpClientFactory
|
||||
.CreateClient(NamedClient.Default)
|
||||
.PostAsync(new Uri(option.WebhookUri), content)
|
||||
.ConfigureAwait(false);
|
||||
await response.LogIfFailedAsync(_logger).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task SendAsync(SlackOption option, Dictionary<string, object> data)
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(option.WebhookUri))
|
||||
{
|
||||
throw new ArgumentException(nameof(option.WebhookUri));
|
||||
}
|
||||
|
||||
if (!SendWebhook(_logger, option, data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
data["SlackUsername"] = option.Username;
|
||||
data["BotUsername"] = option.Username;
|
||||
data["SlackIconUrl"] = option.IconUrl;
|
||||
|
||||
var body = option.GetMessageBody(data);
|
||||
_logger.LogDebug("SendAsync Body: {@Body}", body);
|
||||
using var content = new StringContent(body, Encoding.UTF8, MediaTypeNames.Application.Json);
|
||||
using var response = await _httpClientFactory
|
||||
.CreateClient(NamedClient.Default)
|
||||
.PostAsync(new Uri(option.WebhookUri), content)
|
||||
.ConfigureAwait(false);
|
||||
await response.LogIfFailedAsync(_logger).ConfigureAwait(false);
|
||||
}
|
||||
catch (HttpRequestException e)
|
||||
{
|
||||
_logger.LogWarning(e, "Error sending notification");
|
||||
}
|
||||
_logger.LogWarning(e, "Error sending notification");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,17 @@
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Slack
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Slack;
|
||||
|
||||
/// <summary>
|
||||
/// Slack specific options.
|
||||
/// </summary>
|
||||
public class SlackOption : BaseOption
|
||||
{
|
||||
/// <summary>
|
||||
/// Slack specific options.
|
||||
/// Gets or sets the username.
|
||||
/// </summary>
|
||||
public class SlackOption : BaseOption
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the username.
|
||||
/// </summary>
|
||||
public string Username { get; set; } = string.Empty;
|
||||
public string Username { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the icon url.
|
||||
/// </summary>
|
||||
public string IconUrl { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the icon url.
|
||||
/// </summary>
|
||||
public string IconUrl { get; set; } = string.Empty;
|
||||
}
|
||||
|
@ -4,60 +4,59 @@ using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MimeKit;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Smtp
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Smtp;
|
||||
|
||||
/// <summary>
|
||||
/// Client for the <see cref="SmtpOption"/>.
|
||||
/// </summary>
|
||||
public class SmtpClient : BaseClient, IWebhookClient<SmtpOption>
|
||||
{
|
||||
private readonly ILogger<SmtpClient> _logger;
|
||||
|
||||
/// <summary>
|
||||
/// Client for the <see cref="SmtpOption"/>.
|
||||
/// Initializes a new instance of the <see cref="SmtpClient"/> class.
|
||||
/// </summary>
|
||||
public class SmtpClient : BaseClient, IWebhookClient<SmtpOption>
|
||||
/// <param name="logger">Instance of the <see cref="ILogger{SmtpClient}"/> interface.</param>
|
||||
public SmtpClient(ILogger<SmtpClient> logger)
|
||||
{
|
||||
private readonly ILogger<SmtpClient> _logger;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SmtpClient"/> class.
|
||||
/// </summary>
|
||||
/// <param name="logger">Instance of the <see cref="ILogger{SmtpClient}"/> interface.</param>
|
||||
public SmtpClient(ILogger<SmtpClient> logger)
|
||||
/// <inheritdoc />
|
||||
public async Task SendAsync(SmtpOption option, Dictionary<string, object> data)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger = logger;
|
||||
if (!SendWebhook(_logger, option, data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var message = new MimeMessage();
|
||||
message.From.Add(new MailboxAddress(option.SenderAddress, option.SenderAddress));
|
||||
message.To.Add(new MailboxAddress(option.ReceiverAddress, option.ReceiverAddress));
|
||||
|
||||
message.Subject = option.GetCompiledSubjectTemplate()(data);
|
||||
message.Body = new TextPart(option.IsHtml ? "html" : "plain")
|
||||
{
|
||||
Text = option.GetMessageBody(data)
|
||||
};
|
||||
|
||||
using var smtpClient = new MailKit.Net.Smtp.SmtpClient();
|
||||
await smtpClient.ConnectAsync(option.SmtpServer, option.SmtpPort, option.UseSsl)
|
||||
.ConfigureAwait(false);
|
||||
if (option.UseCredentials)
|
||||
{
|
||||
await smtpClient.AuthenticateAsync(option.Username, option.Password)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await smtpClient.SendAsync(message)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task SendAsync(SmtpOption option, Dictionary<string, object> data)
|
||||
catch (Exception e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!SendWebhook(_logger, option, data))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var message = new MimeMessage();
|
||||
message.From.Add(new MailboxAddress(option.SenderAddress, option.SenderAddress));
|
||||
message.To.Add(new MailboxAddress(option.ReceiverAddress, option.ReceiverAddress));
|
||||
|
||||
message.Subject = option.GetCompiledSubjectTemplate()(data);
|
||||
message.Body = new TextPart(option.IsHtml ? "html" : "plain")
|
||||
{
|
||||
Text = option.GetMessageBody(data)
|
||||
};
|
||||
|
||||
using var smtpClient = new MailKit.Net.Smtp.SmtpClient();
|
||||
await smtpClient.ConnectAsync(option.SmtpServer, option.SmtpPort, option.UseSsl)
|
||||
.ConfigureAwait(false);
|
||||
if (option.UseCredentials)
|
||||
{
|
||||
await smtpClient.AuthenticateAsync(option.Username, option.Password)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await smtpClient.SendAsync(message)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogWarning(e, "Error sending email");
|
||||
}
|
||||
_logger.LogWarning(e, "Error sending email");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,72 +1,71 @@
|
||||
using HandlebarsDotNet;
|
||||
using Jellyfin.Plugin.Webhook.Helpers;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Smtp
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Smtp;
|
||||
|
||||
/// <summary>
|
||||
/// Smtp specific option.
|
||||
/// </summary>
|
||||
public class SmtpOption : BaseOption
|
||||
{
|
||||
private HandlebarsTemplate<object, string>? _compiledSubjectTemplate;
|
||||
|
||||
/// <summary>
|
||||
/// Smtp specific option.
|
||||
/// Gets or sets the sender address.
|
||||
/// </summary>
|
||||
public class SmtpOption : BaseOption
|
||||
public string SenderAddress { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the receiver address.
|
||||
/// </summary>
|
||||
public string ReceiverAddress { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the smtp server.
|
||||
/// </summary>
|
||||
public string SmtpServer { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the smtp port.
|
||||
/// </summary>
|
||||
public int SmtpPort { get; set; } = 25;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether use credentials.
|
||||
/// </summary>
|
||||
public bool UseCredentials { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the username.
|
||||
/// </summary>
|
||||
public string Username { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the password.
|
||||
/// </summary>
|
||||
public string Password { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to use ssl.
|
||||
/// </summary>
|
||||
public bool UseSsl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the body is html.
|
||||
/// </summary>
|
||||
public bool IsHtml { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the email subject template.
|
||||
/// </summary>
|
||||
public string SubjectTemplate { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the compiled handlebars subject template.
|
||||
/// </summary>
|
||||
/// <returns>The compiled handlebars subject template.</returns>
|
||||
public HandlebarsTemplate<object, string> GetCompiledSubjectTemplate()
|
||||
{
|
||||
private HandlebarsTemplate<object, string>? _compiledSubjectTemplate;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the sender address.
|
||||
/// </summary>
|
||||
public string SenderAddress { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the receiver address.
|
||||
/// </summary>
|
||||
public string ReceiverAddress { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the smtp server.
|
||||
/// </summary>
|
||||
public string SmtpServer { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the smtp port.
|
||||
/// </summary>
|
||||
public int SmtpPort { get; set; } = 25;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether use credentials.
|
||||
/// </summary>
|
||||
public bool UseCredentials { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the username.
|
||||
/// </summary>
|
||||
public string Username { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the password.
|
||||
/// </summary>
|
||||
public string Password { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to use ssl.
|
||||
/// </summary>
|
||||
public bool UseSsl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the body is html.
|
||||
/// </summary>
|
||||
public bool IsHtml { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the email subject template.
|
||||
/// </summary>
|
||||
public string SubjectTemplate { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the compiled handlebars subject template.
|
||||
/// </summary>
|
||||
/// <returns>The compiled handlebars subject template.</returns>
|
||||
public HandlebarsTemplate<object, string> GetCompiledSubjectTemplate()
|
||||
{
|
||||
return _compiledSubjectTemplate ??= Handlebars.Compile(HandlebarsFunctionHelpers.Base64Decode(SubjectTemplate));
|
||||
}
|
||||
return _compiledSubjectTemplate ??= Handlebars.Compile(HandlebarsFunctionHelpers.Base64Decode(SubjectTemplate));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,40 +2,39 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Extensions
|
||||
namespace Jellyfin.Plugin.Webhook.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods for <see cref="HttpResponseMessage"/>.
|
||||
/// </summary>
|
||||
public static class HttpResponseMessageExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods for <see cref="HttpResponseMessage"/>.
|
||||
/// Log a warning message if the <paramref name="response"/> contains an error status code.
|
||||
/// </summary>
|
||||
public static class HttpResponseMessageExtensions
|
||||
/// <param name="response">The HTTP response to log if failed.</param>
|
||||
/// <param name="logger">The logger to use to log the warning.</param>
|
||||
/// <returns>A task representing the async operation.</returns>
|
||||
public static async Task LogIfFailedAsync(this HttpResponseMessage response, ILogger logger)
|
||||
{
|
||||
/// <summary>
|
||||
/// Log a warning message if the <paramref name="response"/> contains an error status code.
|
||||
/// </summary>
|
||||
/// <param name="response">The HTTP response to log if failed.</param>
|
||||
/// <param name="logger">The logger to use to log the warning.</param>
|
||||
/// <returns>A task representing the async operation.</returns>
|
||||
public static async Task LogIfFailedAsync(this HttpResponseMessage response, ILogger logger)
|
||||
// Don't log anything for successful responses
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
// Don't log anything for successful responses
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Log the request that caused the failed response, if available
|
||||
var request = response.RequestMessage;
|
||||
if (request is not null)
|
||||
{
|
||||
var requestStr = request.Content is not null
|
||||
? await request.Content.ReadAsStringAsync().ConfigureAwait(false)
|
||||
: "<empty request body>";
|
||||
logger.LogWarning("Notification failed with {Method} request to {Url}: {Content}", request.Method, request.RequestUri, requestStr);
|
||||
}
|
||||
|
||||
// Log the response
|
||||
var responseStr = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
logger.LogWarning("Notification failed with response status code {StatusCode}: {Content}", response.StatusCode, responseStr);
|
||||
return;
|
||||
}
|
||||
|
||||
// Log the request that caused the failed response, if available
|
||||
var request = response.RequestMessage;
|
||||
if (request is not null)
|
||||
{
|
||||
var requestStr = request.Content is not null
|
||||
? await request.Content.ReadAsStringAsync().ConfigureAwait(false)
|
||||
: "<empty request body>";
|
||||
logger.LogWarning("Notification failed with {Method} request to {Url}: {Content}", request.Method, request.RequestUri, requestStr);
|
||||
}
|
||||
|
||||
// Log the response
|
||||
var responseStr = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
logger.LogWarning("Notification failed with response status code {StatusCode}: {Content}", response.StatusCode, responseStr);
|
||||
}
|
||||
}
|
||||
|
@ -13,349 +13,348 @@ using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Updates;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Helpers
|
||||
namespace Jellyfin.Plugin.Webhook.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Data object helpers.
|
||||
/// </summary>
|
||||
public static class DataObjectHelpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Data object helpers.
|
||||
/// Gets the default data object.
|
||||
/// </summary>
|
||||
public static class DataObjectHelpers
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="notificationType">The notification type.</param>
|
||||
/// <returns>The default data object.</returns>
|
||||
public static Dictionary<string, object> GetBaseDataObject(IServerApplicationHost applicationHost, NotificationType notificationType)
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the default data object.
|
||||
/// </summary>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="notificationType">The notification type.</param>
|
||||
/// <returns>The default data object.</returns>
|
||||
public static Dictionary<string, object> GetBaseDataObject(IServerApplicationHost applicationHost, NotificationType notificationType)
|
||||
{
|
||||
var dataObject = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
||||
dataObject["ServerId"] = applicationHost.SystemId;
|
||||
dataObject["ServerName"] = applicationHost.FriendlyName.Escape();
|
||||
dataObject["ServerVersion"] = applicationHost.ApplicationVersionString;
|
||||
dataObject["ServerUrl"] = WebhookPlugin.Instance?.Configuration.ServerUrl ?? "localhost:8096";
|
||||
dataObject[nameof(NotificationType)] = notificationType.ToString();
|
||||
var dataObject = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
||||
dataObject["ServerId"] = applicationHost.SystemId;
|
||||
dataObject["ServerName"] = applicationHost.FriendlyName.Escape();
|
||||
dataObject["ServerVersion"] = applicationHost.ApplicationVersionString;
|
||||
dataObject["ServerUrl"] = WebhookPlugin.Instance?.Configuration.ServerUrl ?? "localhost:8096";
|
||||
dataObject[nameof(NotificationType)] = notificationType.ToString();
|
||||
|
||||
return dataObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get data object from <see cref="BaseItem"/>.
|
||||
/// </summary>
|
||||
/// <param name="dataObject">The existing data object.</param>
|
||||
/// <param name="item">Instance of the <see cref="BaseItem"/>.</param>
|
||||
/// <returns>The data object.</returns>
|
||||
public static Dictionary<string, object> AddBaseItemData(this Dictionary<string, object> dataObject, BaseItem? item)
|
||||
{
|
||||
if (item is null)
|
||||
{
|
||||
return dataObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get data object from <see cref="BaseItem"/>.
|
||||
/// </summary>
|
||||
/// <param name="dataObject">The existing data object.</param>
|
||||
/// <param name="item">Instance of the <see cref="BaseItem"/>.</param>
|
||||
/// <returns>The data object.</returns>
|
||||
public static Dictionary<string, object> AddBaseItemData(this Dictionary<string, object> dataObject, BaseItem? item)
|
||||
dataObject["Timestamp"] = DateTime.Now;
|
||||
dataObject["UtcTimestamp"] = DateTime.UtcNow;
|
||||
dataObject["Name"] = item.Name.Escape();
|
||||
dataObject["Overview"] = item.Overview.Escape();
|
||||
dataObject["Tagline"] = item.Tagline.Escape();
|
||||
dataObject["ItemId"] = item.Id;
|
||||
dataObject["ItemType"] = item.GetType().Name.Escape();
|
||||
dataObject["RunTimeTicks"] = item.RunTimeTicks ?? 0;
|
||||
dataObject["RunTime"] = TimeSpan.FromTicks(item.RunTimeTicks ?? 0).ToString(@"hh\:mm\:ss", CultureInfo.InvariantCulture);
|
||||
|
||||
if (item.ProductionYear is not null)
|
||||
{
|
||||
if (item is null)
|
||||
{
|
||||
return dataObject;
|
||||
}
|
||||
dataObject["Year"] = item.ProductionYear;
|
||||
}
|
||||
|
||||
dataObject["Timestamp"] = DateTime.Now;
|
||||
dataObject["UtcTimestamp"] = DateTime.UtcNow;
|
||||
dataObject["Name"] = item.Name.Escape();
|
||||
dataObject["Overview"] = item.Overview.Escape();
|
||||
dataObject["Tagline"] = item.Tagline.Escape();
|
||||
dataObject["ItemId"] = item.Id;
|
||||
dataObject["ItemType"] = item.GetType().Name.Escape();
|
||||
dataObject["RunTimeTicks"] = item.RunTimeTicks ?? 0;
|
||||
dataObject["RunTime"] = TimeSpan.FromTicks(item.RunTimeTicks ?? 0).ToString(@"hh\:mm\:ss", CultureInfo.InvariantCulture);
|
||||
|
||||
if (item.ProductionYear is not null)
|
||||
{
|
||||
dataObject["Year"] = item.ProductionYear;
|
||||
}
|
||||
|
||||
switch (item)
|
||||
{
|
||||
case Season season:
|
||||
if (!string.IsNullOrEmpty(season.Series?.Name))
|
||||
{
|
||||
dataObject["SeriesName"] = season.Series.Name.Escape();
|
||||
}
|
||||
|
||||
if (season.Series?.ProductionYear is not null)
|
||||
{
|
||||
dataObject["Year"] = season.Series.ProductionYear;
|
||||
}
|
||||
|
||||
if (season.IndexNumber is not null)
|
||||
{
|
||||
dataObject["SeasonNumber"] = season.IndexNumber;
|
||||
dataObject["SeasonNumber00"] = season.IndexNumber.Value.ToString("00", CultureInfo.InvariantCulture);
|
||||
dataObject["SeasonNumber000"] = season.IndexNumber.Value.ToString("000", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
break;
|
||||
case Episode episode:
|
||||
if (!string.IsNullOrEmpty(episode.Series?.Name))
|
||||
{
|
||||
dataObject["SeriesName"] = episode.Series.Name.Escape();
|
||||
}
|
||||
|
||||
if (episode.Season?.IndexNumber is not null)
|
||||
{
|
||||
dataObject["SeasonNumber"] = episode.Season.IndexNumber;
|
||||
dataObject["SeasonNumber00"] = episode.Season.IndexNumber.Value.ToString("00", CultureInfo.InvariantCulture);
|
||||
dataObject["SeasonNumber000"] = episode.Season.IndexNumber.Value.ToString("000", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
if (episode.IndexNumber is not null)
|
||||
{
|
||||
dataObject["EpisodeNumber"] = episode.IndexNumber;
|
||||
dataObject["EpisodeNumber00"] = episode.IndexNumber.Value.ToString("00", CultureInfo.InvariantCulture);
|
||||
dataObject["EpisodeNumber000"] = episode.IndexNumber.Value.ToString("000", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
if (episode.IndexNumberEnd is not null)
|
||||
{
|
||||
dataObject["EpisodeNumberEnd"] = episode.IndexNumberEnd;
|
||||
dataObject["EpisodeNumberEnd00"] = episode.IndexNumberEnd.Value.ToString("00", CultureInfo.InvariantCulture);
|
||||
dataObject["EpisodeNumberEnd000"] = episode.IndexNumberEnd.Value.ToString("000", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
if (episode.Series?.ProductionYear is not null)
|
||||
{
|
||||
dataObject["Year"] = episode.Series.ProductionYear;
|
||||
}
|
||||
|
||||
break;
|
||||
case Audio audio:
|
||||
if (!string.IsNullOrEmpty(audio.Album))
|
||||
{
|
||||
dataObject["Album"] = audio.Album;
|
||||
}
|
||||
|
||||
if (audio.Artists.Count != 0)
|
||||
{
|
||||
// Should all artists be sent?
|
||||
dataObject["Artist"] = audio.Artists[0];
|
||||
}
|
||||
|
||||
if (audio.ProductionYear is not null)
|
||||
{
|
||||
dataObject["Year"] = audio.ProductionYear;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MusicAlbum album:
|
||||
if (album.Artists.Count != 0)
|
||||
{
|
||||
// Should all artists be sent?
|
||||
dataObject["Artist"] = album.Artists[0];
|
||||
}
|
||||
|
||||
if (album.ProductionYear is not null)
|
||||
{
|
||||
dataObject["Year"] = album.ProductionYear;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
foreach (var (providerKey, providerValue) in item.ProviderIds)
|
||||
{
|
||||
dataObject[$"Provider_{providerKey.ToLowerInvariant()}"] = providerValue;
|
||||
}
|
||||
|
||||
var itemMediaStreams = item.GetMediaStreams();
|
||||
if (itemMediaStreams is not null)
|
||||
{
|
||||
var streamCounter = new Dictionary<MediaStreamType, int>();
|
||||
foreach (var mediaStream in itemMediaStreams)
|
||||
switch (item)
|
||||
{
|
||||
case Season season:
|
||||
if (!string.IsNullOrEmpty(season.Series?.Name))
|
||||
{
|
||||
streamCounter.TryGetValue(mediaStream.Type, out var count);
|
||||
streamCounter[mediaStream.Type] = count + 1;
|
||||
var baseKey = $"{mediaStream.Type}_{count}";
|
||||
dataObject["SeriesName"] = season.Series.Name.Escape();
|
||||
}
|
||||
|
||||
switch (mediaStream.Type)
|
||||
if (season.Series?.ProductionYear is not null)
|
||||
{
|
||||
dataObject["Year"] = season.Series.ProductionYear;
|
||||
}
|
||||
|
||||
if (season.IndexNumber is not null)
|
||||
{
|
||||
dataObject["SeasonNumber"] = season.IndexNumber;
|
||||
dataObject["SeasonNumber00"] = season.IndexNumber.Value.ToString("00", CultureInfo.InvariantCulture);
|
||||
dataObject["SeasonNumber000"] = season.IndexNumber.Value.ToString("000", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
break;
|
||||
case Episode episode:
|
||||
if (!string.IsNullOrEmpty(episode.Series?.Name))
|
||||
{
|
||||
dataObject["SeriesName"] = episode.Series.Name.Escape();
|
||||
}
|
||||
|
||||
if (episode.Season?.IndexNumber is not null)
|
||||
{
|
||||
dataObject["SeasonNumber"] = episode.Season.IndexNumber;
|
||||
dataObject["SeasonNumber00"] = episode.Season.IndexNumber.Value.ToString("00", CultureInfo.InvariantCulture);
|
||||
dataObject["SeasonNumber000"] = episode.Season.IndexNumber.Value.ToString("000", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
if (episode.IndexNumber is not null)
|
||||
{
|
||||
dataObject["EpisodeNumber"] = episode.IndexNumber;
|
||||
dataObject["EpisodeNumber00"] = episode.IndexNumber.Value.ToString("00", CultureInfo.InvariantCulture);
|
||||
dataObject["EpisodeNumber000"] = episode.IndexNumber.Value.ToString("000", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
if (episode.IndexNumberEnd is not null)
|
||||
{
|
||||
dataObject["EpisodeNumberEnd"] = episode.IndexNumberEnd;
|
||||
dataObject["EpisodeNumberEnd00"] = episode.IndexNumberEnd.Value.ToString("00", CultureInfo.InvariantCulture);
|
||||
dataObject["EpisodeNumberEnd000"] = episode.IndexNumberEnd.Value.ToString("000", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
if (episode.Series?.ProductionYear is not null)
|
||||
{
|
||||
dataObject["Year"] = episode.Series.ProductionYear;
|
||||
}
|
||||
|
||||
break;
|
||||
case Audio audio:
|
||||
if (!string.IsNullOrEmpty(audio.Album))
|
||||
{
|
||||
dataObject["Album"] = audio.Album;
|
||||
}
|
||||
|
||||
if (audio.Artists.Count != 0)
|
||||
{
|
||||
// Should all artists be sent?
|
||||
dataObject["Artist"] = audio.Artists[0];
|
||||
}
|
||||
|
||||
if (audio.ProductionYear is not null)
|
||||
{
|
||||
dataObject["Year"] = audio.ProductionYear;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MusicAlbum album:
|
||||
if (album.Artists.Count != 0)
|
||||
{
|
||||
// Should all artists be sent?
|
||||
dataObject["Artist"] = album.Artists[0];
|
||||
}
|
||||
|
||||
if (album.ProductionYear is not null)
|
||||
{
|
||||
dataObject["Year"] = album.ProductionYear;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
foreach (var (providerKey, providerValue) in item.ProviderIds)
|
||||
{
|
||||
dataObject[$"Provider_{providerKey.ToLowerInvariant()}"] = providerValue;
|
||||
}
|
||||
|
||||
var itemMediaStreams = item.GetMediaStreams();
|
||||
if (itemMediaStreams is not null)
|
||||
{
|
||||
var streamCounter = new Dictionary<MediaStreamType, int>();
|
||||
foreach (var mediaStream in itemMediaStreams)
|
||||
{
|
||||
streamCounter.TryGetValue(mediaStream.Type, out var count);
|
||||
streamCounter[mediaStream.Type] = count + 1;
|
||||
var baseKey = $"{mediaStream.Type}_{count}";
|
||||
|
||||
switch (mediaStream.Type)
|
||||
{
|
||||
case MediaStreamType.Audio:
|
||||
{
|
||||
case MediaStreamType.Audio:
|
||||
{
|
||||
dataObject[baseKey + "_Title"] = mediaStream.DisplayTitle;
|
||||
dataObject[baseKey + "_Type"] = mediaStream.Type.ToString();
|
||||
dataObject[baseKey + "_Language"] = mediaStream.Language;
|
||||
dataObject[baseKey + "_Codec"] = mediaStream.Codec;
|
||||
dataObject[baseKey + "_Channels"] = mediaStream.Channels ?? 0;
|
||||
dataObject[baseKey + "_Bitrate"] = mediaStream.BitRate ?? 0;
|
||||
dataObject[baseKey + "_SampleRate"] = mediaStream.SampleRate ?? 0;
|
||||
dataObject[baseKey + "_Default"] = mediaStream.IsDefault;
|
||||
break;
|
||||
}
|
||||
|
||||
case MediaStreamType.Video:
|
||||
{
|
||||
dataObject[baseKey + "_Title"] = mediaStream.DisplayTitle;
|
||||
dataObject[baseKey + "_Type"] = mediaStream.Type.ToString();
|
||||
dataObject[baseKey + "_Codec"] = mediaStream.Codec;
|
||||
dataObject[baseKey + "_Profile"] = mediaStream.Profile;
|
||||
dataObject[baseKey + "_Level"] = mediaStream.Level ?? 0;
|
||||
dataObject[baseKey + "_Height"] = mediaStream.Height ?? 0;
|
||||
dataObject[baseKey + "_Width"] = mediaStream.Width ?? 0;
|
||||
dataObject[baseKey + "_AspectRatio"] = mediaStream.AspectRatio;
|
||||
dataObject[baseKey + "_Interlaced"] = mediaStream.IsInterlaced;
|
||||
dataObject[baseKey + "_FrameRate"] = mediaStream.RealFrameRate ?? 0;
|
||||
dataObject[baseKey + "_VideoRange"] = mediaStream.VideoRange;
|
||||
dataObject[baseKey + "_ColorSpace"] = mediaStream.ColorSpace;
|
||||
dataObject[baseKey + "_ColorTransfer"] = mediaStream.ColorTransfer;
|
||||
dataObject[baseKey + "_ColorPrimaries"] = mediaStream.ColorPrimaries;
|
||||
dataObject[baseKey + "_PixelFormat"] = mediaStream.PixelFormat;
|
||||
dataObject[baseKey + "_RefFrames"] = mediaStream.RefFrames ?? 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case MediaStreamType.Subtitle:
|
||||
dataObject[baseKey + "_Title"] = mediaStream.DisplayTitle;
|
||||
dataObject[baseKey + "_Type"] = mediaStream.Type.ToString();
|
||||
dataObject[baseKey + "_Language"] = mediaStream.Language;
|
||||
dataObject[baseKey + "_Codec"] = mediaStream.Codec;
|
||||
dataObject[baseKey + "_Default"] = mediaStream.IsDefault;
|
||||
dataObject[baseKey + "_Forced"] = mediaStream.IsForced;
|
||||
dataObject[baseKey + "_External"] = mediaStream.IsExternal;
|
||||
break;
|
||||
dataObject[baseKey + "_Title"] = mediaStream.DisplayTitle;
|
||||
dataObject[baseKey + "_Type"] = mediaStream.Type.ToString();
|
||||
dataObject[baseKey + "_Language"] = mediaStream.Language;
|
||||
dataObject[baseKey + "_Codec"] = mediaStream.Codec;
|
||||
dataObject[baseKey + "_Channels"] = mediaStream.Channels ?? 0;
|
||||
dataObject[baseKey + "_Bitrate"] = mediaStream.BitRate ?? 0;
|
||||
dataObject[baseKey + "_SampleRate"] = mediaStream.SampleRate ?? 0;
|
||||
dataObject[baseKey + "_Default"] = mediaStream.IsDefault;
|
||||
break;
|
||||
}
|
||||
|
||||
case MediaStreamType.Video:
|
||||
{
|
||||
dataObject[baseKey + "_Title"] = mediaStream.DisplayTitle;
|
||||
dataObject[baseKey + "_Type"] = mediaStream.Type.ToString();
|
||||
dataObject[baseKey + "_Codec"] = mediaStream.Codec;
|
||||
dataObject[baseKey + "_Profile"] = mediaStream.Profile;
|
||||
dataObject[baseKey + "_Level"] = mediaStream.Level ?? 0;
|
||||
dataObject[baseKey + "_Height"] = mediaStream.Height ?? 0;
|
||||
dataObject[baseKey + "_Width"] = mediaStream.Width ?? 0;
|
||||
dataObject[baseKey + "_AspectRatio"] = mediaStream.AspectRatio;
|
||||
dataObject[baseKey + "_Interlaced"] = mediaStream.IsInterlaced;
|
||||
dataObject[baseKey + "_FrameRate"] = mediaStream.RealFrameRate ?? 0;
|
||||
dataObject[baseKey + "_VideoRange"] = mediaStream.VideoRange;
|
||||
dataObject[baseKey + "_ColorSpace"] = mediaStream.ColorSpace;
|
||||
dataObject[baseKey + "_ColorTransfer"] = mediaStream.ColorTransfer;
|
||||
dataObject[baseKey + "_ColorPrimaries"] = mediaStream.ColorPrimaries;
|
||||
dataObject[baseKey + "_PixelFormat"] = mediaStream.PixelFormat;
|
||||
dataObject[baseKey + "_RefFrames"] = mediaStream.RefFrames ?? 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case MediaStreamType.Subtitle:
|
||||
dataObject[baseKey + "_Title"] = mediaStream.DisplayTitle;
|
||||
dataObject[baseKey + "_Type"] = mediaStream.Type.ToString();
|
||||
dataObject[baseKey + "_Language"] = mediaStream.Language;
|
||||
dataObject[baseKey + "_Codec"] = mediaStream.Codec;
|
||||
dataObject[baseKey + "_Default"] = mediaStream.IsDefault;
|
||||
dataObject[baseKey + "_Forced"] = mediaStream.IsForced;
|
||||
dataObject[baseKey + "_External"] = mediaStream.IsExternal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return dataObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add playback progress data.
|
||||
/// </summary>
|
||||
/// <param name="dataObject">The data object.</param>
|
||||
/// <param name="playbackProgressEventArgs">The playback progress event args.</param>
|
||||
/// <returns>The modified data object.</returns>
|
||||
public static Dictionary<string, object> AddPlaybackProgressData(this Dictionary<string, object> dataObject, PlaybackProgressEventArgs playbackProgressEventArgs)
|
||||
{
|
||||
dataObject[nameof(playbackProgressEventArgs.PlaybackPositionTicks)] = playbackProgressEventArgs.PlaybackPositionTicks ?? 0;
|
||||
dataObject["PlaybackPosition"] = TimeSpan.FromTicks(playbackProgressEventArgs.PlaybackPositionTicks ?? 0).ToString(@"hh\:mm\:ss", CultureInfo.InvariantCulture);
|
||||
dataObject[nameof(playbackProgressEventArgs.MediaSourceId)] = playbackProgressEventArgs.MediaSourceId;
|
||||
dataObject[nameof(playbackProgressEventArgs.IsPaused)] = playbackProgressEventArgs.IsPaused;
|
||||
dataObject[nameof(playbackProgressEventArgs.IsAutomated)] = playbackProgressEventArgs.IsAutomated;
|
||||
dataObject[nameof(playbackProgressEventArgs.DeviceId)] = playbackProgressEventArgs.DeviceId;
|
||||
dataObject[nameof(playbackProgressEventArgs.DeviceName)] = playbackProgressEventArgs.DeviceName;
|
||||
dataObject[nameof(playbackProgressEventArgs.ClientName)] = playbackProgressEventArgs.ClientName;
|
||||
|
||||
return dataObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add user data.
|
||||
/// </summary>
|
||||
/// <param name="dataObject">The data object.</param>
|
||||
/// <param name="user">The user to add.</param>
|
||||
/// <returns>The modified data object.</returns>
|
||||
public static Dictionary<string, object> AddUserData(this Dictionary<string, object> dataObject, UserDto user)
|
||||
{
|
||||
dataObject["NotificationUsername"] = user.Name.Escape();
|
||||
dataObject["UserId"] = user.Id;
|
||||
dataObject[nameof(user.LastLoginDate)] = user.LastLoginDate ?? DateTime.UtcNow;
|
||||
dataObject[nameof(user.LastActivityDate)] = user.LastActivityDate ?? DateTime.MinValue;
|
||||
|
||||
return dataObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add user data.
|
||||
/// </summary>
|
||||
/// <param name="dataObject">The data object.</param>
|
||||
/// <param name="user">The user to add.</param>
|
||||
/// <returns>The modified data object.</returns>
|
||||
public static Dictionary<string, object> AddUserData(this Dictionary<string, object> dataObject, User user)
|
||||
{
|
||||
dataObject["NotificationUsername"] = user.Username.Escape();
|
||||
dataObject["UserId"] = user.Id;
|
||||
dataObject[nameof(user.LastLoginDate)] = user.LastLoginDate ?? DateTime.UtcNow;
|
||||
dataObject[nameof(user.LastActivityDate)] = user.LastActivityDate ?? DateTime.MinValue;
|
||||
|
||||
return dataObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add session info data.
|
||||
/// </summary>
|
||||
/// <param name="dataObject">The data object.</param>
|
||||
/// <param name="sessionInfo">The session info to add.</param>
|
||||
/// <returns>The modified data object.</returns>
|
||||
public static Dictionary<string, object> AddSessionInfoData(this Dictionary<string, object> dataObject, SessionInfo sessionInfo)
|
||||
{
|
||||
dataObject[nameof(sessionInfo.Id)] = sessionInfo.Id;
|
||||
dataObject[nameof(sessionInfo.UserId)] = sessionInfo.UserId;
|
||||
dataObject["NotificationUsername"] = sessionInfo.UserName.Escape();
|
||||
dataObject[nameof(sessionInfo.Client)] = sessionInfo.Client.Escape();
|
||||
dataObject[nameof(sessionInfo.LastActivityDate)] = sessionInfo.LastActivityDate;
|
||||
dataObject[nameof(sessionInfo.LastPlaybackCheckIn)] = sessionInfo.LastPlaybackCheckIn;
|
||||
dataObject[nameof(sessionInfo.DeviceName)] = sessionInfo.DeviceName.Escape();
|
||||
dataObject[nameof(sessionInfo.DeviceId)] = sessionInfo.DeviceId;
|
||||
|
||||
return dataObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add plugin installation info.
|
||||
/// </summary>
|
||||
/// <param name="dataObject">The data object.</param>
|
||||
/// <param name="installationInfo">The plugin installation info to add.</param>
|
||||
/// <returns>The modified data object.</returns>
|
||||
public static Dictionary<string, object> AddPluginInstallationInfo(this Dictionary<string, object> dataObject, InstallationInfo installationInfo)
|
||||
{
|
||||
dataObject["PluginId"] = installationInfo.Id;
|
||||
dataObject["PluginName"] = installationInfo.Name.Escape();
|
||||
dataObject["PluginVersion"] = installationInfo.Version;
|
||||
dataObject["PluginChangelog"] = installationInfo.Changelog.Escape();
|
||||
dataObject["PluginChecksum"] = installationInfo.Checksum;
|
||||
dataObject["PluginSourceUrl"] = installationInfo.SourceUrl;
|
||||
|
||||
return dataObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add exception info.
|
||||
/// </summary>
|
||||
/// <param name="dataObject">The data object.</param>
|
||||
/// <param name="exception">The exception to add.</param>
|
||||
/// <returns>The modified data object.</returns>
|
||||
public static Dictionary<string, object> AddExceptionInfo(this Dictionary<string, object> dataObject, Exception exception)
|
||||
{
|
||||
dataObject["ExceptionMessage"] = exception.Message.Escape();
|
||||
dataObject["ExceptionMessageInner"] = exception.InnerException?.Message ?? string.Empty;
|
||||
|
||||
return dataObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add user item data.
|
||||
/// </summary>
|
||||
/// <param name="dataObject">The data object.</param>
|
||||
/// <param name="userItemData">The user item data.</param>
|
||||
/// <returns>The modified data object.</returns>
|
||||
public static Dictionary<string, object> AddUserItemData(this Dictionary<string, object> dataObject, UserItemData userItemData)
|
||||
{
|
||||
dataObject["Likes"] = userItemData.Likes ?? false;
|
||||
dataObject["Rating"] = userItemData.Rating ?? 0;
|
||||
dataObject["PlaybackPositionTicks"] = userItemData.PlaybackPositionTicks;
|
||||
dataObject["PlaybackPosition"] = TimeSpan.FromTicks(userItemData.PlaybackPositionTicks).ToString(@"hh\:mm\:ss", CultureInfo.InvariantCulture);
|
||||
dataObject["PlayCount"] = userItemData.PlayCount;
|
||||
dataObject["Favorite"] = userItemData.IsFavorite;
|
||||
dataObject["Played"] = userItemData.Played;
|
||||
dataObject["AudioStreamIndex"] = userItemData.AudioStreamIndex ?? -1;
|
||||
dataObject["SubtitleStreamIndex"] = userItemData.SubtitleStreamIndex ?? -1;
|
||||
if (userItemData.LastPlayedDate.HasValue)
|
||||
{
|
||||
dataObject["LastPlayedDate"] = userItemData.LastPlayedDate;
|
||||
}
|
||||
|
||||
return dataObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Escape quotes for proper json.
|
||||
/// </summary>
|
||||
/// <param name="input">Input string.</param>
|
||||
/// <returns>Escaped string.</returns>
|
||||
private static string Escape(this string? input)
|
||||
=> input?.Replace("\"", "\\\"", StringComparison.Ordinal) ?? string.Empty;
|
||||
return dataObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add playback progress data.
|
||||
/// </summary>
|
||||
/// <param name="dataObject">The data object.</param>
|
||||
/// <param name="playbackProgressEventArgs">The playback progress event args.</param>
|
||||
/// <returns>The modified data object.</returns>
|
||||
public static Dictionary<string, object> AddPlaybackProgressData(this Dictionary<string, object> dataObject, PlaybackProgressEventArgs playbackProgressEventArgs)
|
||||
{
|
||||
dataObject[nameof(playbackProgressEventArgs.PlaybackPositionTicks)] = playbackProgressEventArgs.PlaybackPositionTicks ?? 0;
|
||||
dataObject["PlaybackPosition"] = TimeSpan.FromTicks(playbackProgressEventArgs.PlaybackPositionTicks ?? 0).ToString(@"hh\:mm\:ss", CultureInfo.InvariantCulture);
|
||||
dataObject[nameof(playbackProgressEventArgs.MediaSourceId)] = playbackProgressEventArgs.MediaSourceId;
|
||||
dataObject[nameof(playbackProgressEventArgs.IsPaused)] = playbackProgressEventArgs.IsPaused;
|
||||
dataObject[nameof(playbackProgressEventArgs.IsAutomated)] = playbackProgressEventArgs.IsAutomated;
|
||||
dataObject[nameof(playbackProgressEventArgs.DeviceId)] = playbackProgressEventArgs.DeviceId;
|
||||
dataObject[nameof(playbackProgressEventArgs.DeviceName)] = playbackProgressEventArgs.DeviceName;
|
||||
dataObject[nameof(playbackProgressEventArgs.ClientName)] = playbackProgressEventArgs.ClientName;
|
||||
|
||||
return dataObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add user data.
|
||||
/// </summary>
|
||||
/// <param name="dataObject">The data object.</param>
|
||||
/// <param name="user">The user to add.</param>
|
||||
/// <returns>The modified data object.</returns>
|
||||
public static Dictionary<string, object> AddUserData(this Dictionary<string, object> dataObject, UserDto user)
|
||||
{
|
||||
dataObject["NotificationUsername"] = user.Name.Escape();
|
||||
dataObject["UserId"] = user.Id;
|
||||
dataObject[nameof(user.LastLoginDate)] = user.LastLoginDate ?? DateTime.UtcNow;
|
||||
dataObject[nameof(user.LastActivityDate)] = user.LastActivityDate ?? DateTime.MinValue;
|
||||
|
||||
return dataObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add user data.
|
||||
/// </summary>
|
||||
/// <param name="dataObject">The data object.</param>
|
||||
/// <param name="user">The user to add.</param>
|
||||
/// <returns>The modified data object.</returns>
|
||||
public static Dictionary<string, object> AddUserData(this Dictionary<string, object> dataObject, User user)
|
||||
{
|
||||
dataObject["NotificationUsername"] = user.Username.Escape();
|
||||
dataObject["UserId"] = user.Id;
|
||||
dataObject[nameof(user.LastLoginDate)] = user.LastLoginDate ?? DateTime.UtcNow;
|
||||
dataObject[nameof(user.LastActivityDate)] = user.LastActivityDate ?? DateTime.MinValue;
|
||||
|
||||
return dataObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add session info data.
|
||||
/// </summary>
|
||||
/// <param name="dataObject">The data object.</param>
|
||||
/// <param name="sessionInfo">The session info to add.</param>
|
||||
/// <returns>The modified data object.</returns>
|
||||
public static Dictionary<string, object> AddSessionInfoData(this Dictionary<string, object> dataObject, SessionInfo sessionInfo)
|
||||
{
|
||||
dataObject[nameof(sessionInfo.Id)] = sessionInfo.Id;
|
||||
dataObject[nameof(sessionInfo.UserId)] = sessionInfo.UserId;
|
||||
dataObject["NotificationUsername"] = sessionInfo.UserName.Escape();
|
||||
dataObject[nameof(sessionInfo.Client)] = sessionInfo.Client.Escape();
|
||||
dataObject[nameof(sessionInfo.LastActivityDate)] = sessionInfo.LastActivityDate;
|
||||
dataObject[nameof(sessionInfo.LastPlaybackCheckIn)] = sessionInfo.LastPlaybackCheckIn;
|
||||
dataObject[nameof(sessionInfo.DeviceName)] = sessionInfo.DeviceName.Escape();
|
||||
dataObject[nameof(sessionInfo.DeviceId)] = sessionInfo.DeviceId;
|
||||
|
||||
return dataObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add plugin installation info.
|
||||
/// </summary>
|
||||
/// <param name="dataObject">The data object.</param>
|
||||
/// <param name="installationInfo">The plugin installation info to add.</param>
|
||||
/// <returns>The modified data object.</returns>
|
||||
public static Dictionary<string, object> AddPluginInstallationInfo(this Dictionary<string, object> dataObject, InstallationInfo installationInfo)
|
||||
{
|
||||
dataObject["PluginId"] = installationInfo.Id;
|
||||
dataObject["PluginName"] = installationInfo.Name.Escape();
|
||||
dataObject["PluginVersion"] = installationInfo.Version;
|
||||
dataObject["PluginChangelog"] = installationInfo.Changelog.Escape();
|
||||
dataObject["PluginChecksum"] = installationInfo.Checksum;
|
||||
dataObject["PluginSourceUrl"] = installationInfo.SourceUrl;
|
||||
|
||||
return dataObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add exception info.
|
||||
/// </summary>
|
||||
/// <param name="dataObject">The data object.</param>
|
||||
/// <param name="exception">The exception to add.</param>
|
||||
/// <returns>The modified data object.</returns>
|
||||
public static Dictionary<string, object> AddExceptionInfo(this Dictionary<string, object> dataObject, Exception exception)
|
||||
{
|
||||
dataObject["ExceptionMessage"] = exception.Message.Escape();
|
||||
dataObject["ExceptionMessageInner"] = exception.InnerException?.Message ?? string.Empty;
|
||||
|
||||
return dataObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add user item data.
|
||||
/// </summary>
|
||||
/// <param name="dataObject">The data object.</param>
|
||||
/// <param name="userItemData">The user item data.</param>
|
||||
/// <returns>The modified data object.</returns>
|
||||
public static Dictionary<string, object> AddUserItemData(this Dictionary<string, object> dataObject, UserItemData userItemData)
|
||||
{
|
||||
dataObject["Likes"] = userItemData.Likes ?? false;
|
||||
dataObject["Rating"] = userItemData.Rating ?? 0;
|
||||
dataObject["PlaybackPositionTicks"] = userItemData.PlaybackPositionTicks;
|
||||
dataObject["PlaybackPosition"] = TimeSpan.FromTicks(userItemData.PlaybackPositionTicks).ToString(@"hh\:mm\:ss", CultureInfo.InvariantCulture);
|
||||
dataObject["PlayCount"] = userItemData.PlayCount;
|
||||
dataObject["Favorite"] = userItemData.IsFavorite;
|
||||
dataObject["Played"] = userItemData.Played;
|
||||
dataObject["AudioStreamIndex"] = userItemData.AudioStreamIndex ?? -1;
|
||||
dataObject["SubtitleStreamIndex"] = userItemData.SubtitleStreamIndex ?? -1;
|
||||
if (userItemData.LastPlayedDate.HasValue)
|
||||
{
|
||||
dataObject["LastPlayedDate"] = userItemData.LastPlayedDate;
|
||||
}
|
||||
|
||||
return dataObject;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Escape quotes for proper json.
|
||||
/// </summary>
|
||||
/// <param name="input">Input string.</param>
|
||||
/// <returns>Escaped string.</returns>
|
||||
private static string Escape(this string? input)
|
||||
=> input?.Replace("\"", "\\\"", StringComparison.Ordinal) ?? string.Empty;
|
||||
}
|
||||
|
@ -2,88 +2,87 @@
|
||||
using System.Globalization;
|
||||
using HandlebarsDotNet;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Helpers
|
||||
namespace Jellyfin.Plugin.Webhook.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Handlebar helpers.
|
||||
/// </summary>
|
||||
public static class HandlebarsFunctionHelpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Handlebar helpers.
|
||||
/// </summary>
|
||||
public static class HandlebarsFunctionHelpers
|
||||
private static readonly HandlebarsBlockHelper StringEqualityHelper = (output, options, context, arguments) =>
|
||||
{
|
||||
private static readonly HandlebarsBlockHelper StringEqualityHelper = (output, options, context, arguments) =>
|
||||
if (arguments.Length != 2)
|
||||
{
|
||||
if (arguments.Length != 2)
|
||||
{
|
||||
throw new HandlebarsException("{{if_equals}} helper must have exactly two arguments");
|
||||
}
|
||||
|
||||
var left = GetStringValue(arguments[0]);
|
||||
var right = GetStringValue(arguments[1]);
|
||||
if (string.Equals(left, right, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
options.Template(output, context);
|
||||
}
|
||||
else
|
||||
{
|
||||
options.Inverse(output, context);
|
||||
}
|
||||
};
|
||||
|
||||
private static readonly HandlebarsBlockHelper StringExistHelper = (output, options, context, arguments) =>
|
||||
{
|
||||
if (arguments.Length != 1)
|
||||
{
|
||||
throw new HandlebarsException("{{if_exist}} helper must have exactly one argument");
|
||||
}
|
||||
|
||||
var arg = GetStringValue(arguments[0]);
|
||||
if (string.IsNullOrEmpty(arg))
|
||||
{
|
||||
options.Inverse(output, context);
|
||||
}
|
||||
else
|
||||
{
|
||||
options.Template(output, context);
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Register handlebars helpers.
|
||||
/// </summary>
|
||||
public static void RegisterHelpers()
|
||||
{
|
||||
Handlebars.RegisterHelper("if_equals", StringEqualityHelper);
|
||||
Handlebars.RegisterHelper("if_exist", StringExistHelper);
|
||||
Handlebars.RegisterHelper("link_to", (writer, context, parameters) =>
|
||||
{
|
||||
writer.WriteSafeString($"<a href='{parameters["url"]}'>{context["text"]}</a>");
|
||||
});
|
||||
throw new HandlebarsException("{{if_equals}} helper must have exactly two arguments");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Base 64 decode.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The template is stored as base64 in config.
|
||||
/// </remarks>
|
||||
/// <param name="base64EncodedData">The encoded data.</param>
|
||||
/// <returns>The decoded string.</returns>
|
||||
public static string Base64Decode(string? base64EncodedData)
|
||||
var left = GetStringValue(arguments[0]);
|
||||
var right = GetStringValue(arguments[1]);
|
||||
if (string.Equals(left, right, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (string.IsNullOrEmpty(base64EncodedData))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
options.Template(output, context);
|
||||
}
|
||||
else
|
||||
{
|
||||
options.Inverse(output, context);
|
||||
}
|
||||
};
|
||||
|
||||
var base64EncodedBytes = Convert.FromBase64String(base64EncodedData);
|
||||
return System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
|
||||
private static readonly HandlebarsBlockHelper StringExistHelper = (output, options, context, arguments) =>
|
||||
{
|
||||
if (arguments.Length != 1)
|
||||
{
|
||||
throw new HandlebarsException("{{if_exist}} helper must have exactly one argument");
|
||||
}
|
||||
|
||||
private static string? GetStringValue(object? input)
|
||||
var arg = GetStringValue(arguments[0]);
|
||||
if (string.IsNullOrEmpty(arg))
|
||||
{
|
||||
// UndefinedBindingResult means the parameter was a part of the provided dataset.
|
||||
return input is UndefinedBindingResult or null
|
||||
? null
|
||||
: Convert.ToString(input, CultureInfo.InvariantCulture);
|
||||
options.Inverse(output, context);
|
||||
}
|
||||
else
|
||||
{
|
||||
options.Template(output, context);
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Register handlebars helpers.
|
||||
/// </summary>
|
||||
public static void RegisterHelpers()
|
||||
{
|
||||
Handlebars.RegisterHelper("if_equals", StringEqualityHelper);
|
||||
Handlebars.RegisterHelper("if_exist", StringExistHelper);
|
||||
Handlebars.RegisterHelper("link_to", (writer, context, parameters) =>
|
||||
{
|
||||
writer.WriteSafeString($"<a href='{parameters["url"]}'>{context["text"]}</a>");
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Base 64 decode.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The template is stored as base64 in config.
|
||||
/// </remarks>
|
||||
/// <param name="base64EncodedData">The encoded data.</param>
|
||||
/// <returns>The decoded string.</returns>
|
||||
public static string Base64Decode(string? base64EncodedData)
|
||||
{
|
||||
if (string.IsNullOrEmpty(base64EncodedData))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
var base64EncodedBytes = Convert.FromBase64String(base64EncodedData);
|
||||
return System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
|
||||
}
|
||||
|
||||
private static string? GetStringValue(object? input)
|
||||
{
|
||||
// UndefinedBindingResult means the parameter was a part of the provided dataset.
|
||||
return input is UndefinedBindingResult or null
|
||||
? null
|
||||
: Convert.ToString(input, CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
|
@ -3,20 +3,19 @@ using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Jellyfin.Plugin.Webhook.Destinations;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook
|
||||
namespace Jellyfin.Plugin.Webhook;
|
||||
|
||||
/// <summary>
|
||||
/// Webhook sender interface.
|
||||
/// </summary>
|
||||
public interface IWebhookSender
|
||||
{
|
||||
/// <summary>
|
||||
/// Webhook sender interface.
|
||||
/// Send notification with item type.
|
||||
/// </summary>
|
||||
public interface IWebhookSender
|
||||
{
|
||||
/// <summary>
|
||||
/// Send notification with item type.
|
||||
/// </summary>
|
||||
/// <param name="notificationType">The notification type.</param>
|
||||
/// <param name="itemData">The item data.</param>
|
||||
/// <param name="itemType">The item type. Default <c>null</c>.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
Task SendNotification(NotificationType notificationType, Dictionary<string, object> itemData, Type? itemType = null);
|
||||
}
|
||||
/// <param name="notificationType">The notification type.</param>
|
||||
/// <param name="itemData">The item data.</param>
|
||||
/// <param name="itemType">The item type. Default <c>null</c>.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
Task SendNotification(NotificationType notificationType, Dictionary<string, object> itemData, Type? itemType = null);
|
||||
}
|
||||
|
@ -15,12 +15,12 @@
|
||||
<PackageReference Include="MailKit" Version="3.4.1" />
|
||||
<PackageReference Include="Handlebars.Net" Version="2.1.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="6.*" />
|
||||
<PackageReference Include="MQTTnet.Extensions.ManagedClient" Version="4.1.0.247" />
|
||||
<PackageReference Include="MQTTnet.Extensions.ManagedClient" Version="4.1.1.318" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
|
||||
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
|
@ -1,30 +1,29 @@
|
||||
using System;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Models
|
||||
namespace Jellyfin.Plugin.Webhook.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Queued item container.
|
||||
/// </summary>
|
||||
public class QueuedItemContainer
|
||||
{
|
||||
/// <summary>
|
||||
/// Queued item container.
|
||||
/// Initializes a new instance of the <see cref="QueuedItemContainer"/> class.
|
||||
/// </summary>
|
||||
public class QueuedItemContainer
|
||||
/// <param name="id">The item id.</param>
|
||||
public QueuedItemContainer(Guid id)
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="QueuedItemContainer"/> class.
|
||||
/// </summary>
|
||||
/// <param name="id">The item id.</param>
|
||||
public QueuedItemContainer(Guid id)
|
||||
{
|
||||
ItemId = id;
|
||||
RetryCount = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current retry count.
|
||||
/// </summary>
|
||||
public int RetryCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current item id.
|
||||
/// </summary>
|
||||
public Guid ItemId { get; set; }
|
||||
ItemId = id;
|
||||
RetryCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current retry count.
|
||||
/// </summary>
|
||||
public int RetryCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the current item id.
|
||||
/// </summary>
|
||||
public Guid ItemId { get; set; }
|
||||
}
|
||||
|
@ -6,48 +6,47 @@ using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Events;
|
||||
using MediaBrowser.Controller.Session;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers;
|
||||
|
||||
/// <summary>
|
||||
/// Authentication failure notifier.
|
||||
/// </summary>
|
||||
public class AuthenticationFailureNotifier : IEventConsumer<GenericEventArgs<AuthenticationRequest>>
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
|
||||
/// <summary>
|
||||
/// Authentication failure notifier.
|
||||
/// Initializes a new instance of the <see cref="AuthenticationFailureNotifier"/> class.
|
||||
/// </summary>
|
||||
public class AuthenticationFailureNotifier : IEventConsumer<GenericEventArgs<AuthenticationRequest>>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public AuthenticationFailureNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AuthenticationFailureNotifier"/> class.
|
||||
/// </summary>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public AuthenticationFailureNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(GenericEventArgs<AuthenticationRequest> eventArgs)
|
||||
{
|
||||
if (eventArgs.Argument is null)
|
||||
{
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
return;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(GenericEventArgs<AuthenticationRequest> eventArgs)
|
||||
{
|
||||
if (eventArgs.Argument is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.AuthenticationFailure);
|
||||
dataObject[nameof(eventArgs.Argument.App)] = eventArgs.Argument.App;
|
||||
dataObject[nameof(eventArgs.Argument.Username)] = eventArgs.Argument.Username;
|
||||
dataObject[nameof(eventArgs.Argument.UserId)] = eventArgs.Argument.UserId;
|
||||
dataObject[nameof(eventArgs.Argument.AppVersion)] = eventArgs.Argument.AppVersion;
|
||||
dataObject[nameof(eventArgs.Argument.DeviceId)] = eventArgs.Argument.DeviceId;
|
||||
dataObject[nameof(eventArgs.Argument.DeviceName)] = eventArgs.Argument.DeviceName;
|
||||
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.AuthenticationFailure);
|
||||
dataObject[nameof(eventArgs.Argument.App)] = eventArgs.Argument.App;
|
||||
dataObject[nameof(eventArgs.Argument.Username)] = eventArgs.Argument.Username;
|
||||
dataObject[nameof(eventArgs.Argument.UserId)] = eventArgs.Argument.UserId;
|
||||
dataObject[nameof(eventArgs.Argument.AppVersion)] = eventArgs.Argument.AppVersion;
|
||||
dataObject[nameof(eventArgs.Argument.DeviceId)] = eventArgs.Argument.DeviceId;
|
||||
dataObject[nameof(eventArgs.Argument.DeviceName)] = eventArgs.Argument.DeviceName;
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.AuthenticationFailure, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
await _webhookSender.SendNotification(NotificationType.AuthenticationFailure, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
@ -6,43 +6,42 @@ using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Authentication;
|
||||
using MediaBrowser.Controller.Events;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers;
|
||||
|
||||
/// <summary>
|
||||
/// Authentication success notifier.
|
||||
/// </summary>
|
||||
public class AuthenticationSuccessNotifier : IEventConsumer<GenericEventArgs<AuthenticationResult>>
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
|
||||
/// <summary>
|
||||
/// Authentication success notifier.
|
||||
/// Initializes a new instance of the <see cref="AuthenticationSuccessNotifier"/> class.
|
||||
/// </summary>
|
||||
public class AuthenticationSuccessNotifier : IEventConsumer<GenericEventArgs<AuthenticationResult>>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public AuthenticationSuccessNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AuthenticationSuccessNotifier"/> class.
|
||||
/// </summary>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public AuthenticationSuccessNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(GenericEventArgs<AuthenticationResult> eventArgs)
|
||||
{
|
||||
if (eventArgs.Argument is null)
|
||||
{
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
return;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(GenericEventArgs<AuthenticationResult> eventArgs)
|
||||
{
|
||||
if (eventArgs.Argument is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.AuthenticationSuccess)
|
||||
.AddUserData(eventArgs.Argument.User);
|
||||
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.AuthenticationSuccess)
|
||||
.AddUserData(eventArgs.Argument.User);
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.AuthenticationSuccess, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
await _webhookSender.SendNotification(NotificationType.AuthenticationSuccess, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
@ -6,48 +6,47 @@ using Jellyfin.Plugin.Webhook.Helpers;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Notifications;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers;
|
||||
|
||||
/// <summary>
|
||||
/// Generic notifier.
|
||||
/// </summary>
|
||||
public class GenericNotifier : INotificationService
|
||||
{
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
|
||||
/// <summary>
|
||||
/// Generic notifier.
|
||||
/// Initializes a new instance of the <see cref="GenericNotifier"/> class.
|
||||
/// </summary>
|
||||
public class GenericNotifier : INotificationService
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
public GenericNotifier(IWebhookSender webhookSender, IServerApplicationHost applicationHost)
|
||||
{
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GenericNotifier"/> class.
|
||||
/// </summary>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
public GenericNotifier(IWebhookSender webhookSender, IServerApplicationHost applicationHost)
|
||||
{
|
||||
_webhookSender = webhookSender;
|
||||
_applicationHost = applicationHost;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name => "Webhook: Generic Notifier";
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task SendNotification(UserNotification request, CancellationToken cancellationToken)
|
||||
{
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.Generic);
|
||||
dataObject[nameof(request.Name)] = request.Name;
|
||||
dataObject[nameof(request.Description)] = request.Description;
|
||||
dataObject[nameof(request.Date)] = request.Date;
|
||||
dataObject[nameof(request.Level)] = request.Level;
|
||||
dataObject[nameof(request.Url)] = request.Url;
|
||||
dataObject[nameof(request.User.Username)] = request.User.Username;
|
||||
dataObject["UserId"] = request.User.Id;
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.Generic, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsEnabledForUser(User user) => true;
|
||||
_webhookSender = webhookSender;
|
||||
_applicationHost = applicationHost;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name => "Webhook: Generic Notifier";
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task SendNotification(UserNotification request, CancellationToken cancellationToken)
|
||||
{
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.Generic);
|
||||
dataObject[nameof(request.Name)] = request.Name;
|
||||
dataObject[nameof(request.Description)] = request.Description;
|
||||
dataObject[nameof(request.Date)] = request.Date;
|
||||
dataObject[nameof(request.Level)] = request.Level;
|
||||
dataObject[nameof(request.Url)] = request.Url;
|
||||
dataObject[nameof(request.User.Username)] = request.User.Username;
|
||||
dataObject["UserId"] = request.User.Id;
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.Generic, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsEnabledForUser(User user) => true;
|
||||
}
|
||||
|
@ -1,23 +1,22 @@
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers.ItemAddedNotifier
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers.ItemAddedNotifier;
|
||||
|
||||
/// <summary>
|
||||
/// Item added manager interface.
|
||||
/// </summary>
|
||||
public interface IItemAddedManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Item added manager interface.
|
||||
/// Process the current queue.
|
||||
/// </summary>
|
||||
public interface IItemAddedManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Process the current queue.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
public Task ProcessItemsAsync();
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
public Task ProcessItemsAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Add item to process queue.
|
||||
/// </summary>
|
||||
/// <param name="item">The added item.</param>
|
||||
public void AddItem(BaseItem item);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Add item to process queue.
|
||||
/// </summary>
|
||||
/// <param name="item">The added item.</param>
|
||||
public void AddItem(BaseItem item);
|
||||
}
|
||||
|
@ -9,86 +9,85 @@ using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers.ItemAddedNotifier
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers.ItemAddedNotifier;
|
||||
|
||||
/// <inheritdoc />
|
||||
public class ItemAddedManager : IItemAddedManager
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public class ItemAddedManager : IItemAddedManager
|
||||
private const int MaxRetries = 10;
|
||||
private readonly ILogger<ItemAddedManager> _logger;
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
private readonly ConcurrentDictionary<Guid, QueuedItemContainer> _itemProcessQueue;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ItemAddedManager"/> class.
|
||||
/// </summary>
|
||||
/// <param name="logger">Instance of the <see cref="ILogger{ItemAddedManager}"/> interface.</param>
|
||||
/// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public ItemAddedManager(
|
||||
ILogger<ItemAddedManager> logger,
|
||||
ILibraryManager libraryManager,
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
private const int MaxRetries = 10;
|
||||
private readonly ILogger<ItemAddedManager> _logger;
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
private readonly ConcurrentDictionary<Guid, QueuedItemContainer> _itemProcessQueue;
|
||||
_logger = logger;
|
||||
_libraryManager = libraryManager;
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
_itemProcessQueue = new ConcurrentDictionary<Guid, QueuedItemContainer>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ItemAddedManager"/> class.
|
||||
/// </summary>
|
||||
/// <param name="logger">Instance of the <see cref="ILogger{ItemAddedManager}"/> interface.</param>
|
||||
/// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public ItemAddedManager(
|
||||
ILogger<ItemAddedManager> logger,
|
||||
ILibraryManager libraryManager,
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
/// <inheritdoc />
|
||||
public async Task ProcessItemsAsync()
|
||||
{
|
||||
_logger.LogDebug("ProcessItemsAsync");
|
||||
// Attempt to process all items in queue.
|
||||
var currentItems = _itemProcessQueue.ToArray();
|
||||
foreach (var (key, container) in currentItems)
|
||||
{
|
||||
_logger = logger;
|
||||
_libraryManager = libraryManager;
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
_itemProcessQueue = new ConcurrentDictionary<Guid, QueuedItemContainer>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task ProcessItemsAsync()
|
||||
{
|
||||
_logger.LogDebug("ProcessItemsAsync");
|
||||
// Attempt to process all items in queue.
|
||||
var currentItems = _itemProcessQueue.ToArray();
|
||||
foreach (var (key, container) in currentItems)
|
||||
var item = _libraryManager.GetItemById(key);
|
||||
if (item is null)
|
||||
{
|
||||
var item = _libraryManager.GetItemById(key);
|
||||
if (item is null)
|
||||
{
|
||||
// Remove item from queue.
|
||||
_itemProcessQueue.TryRemove(key, out _);
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.LogDebug("Item {ItemName}", item.Name);
|
||||
|
||||
// Metadata not refreshed yet and under retry limit.
|
||||
if (item.ProviderIds.Keys.Count == 0 && container.RetryCount < MaxRetries)
|
||||
{
|
||||
_logger.LogDebug("Requeue {ItemName}, no provider ids", item.Name);
|
||||
container.RetryCount++;
|
||||
_itemProcessQueue.AddOrUpdate(key, container, (_, _) => container);
|
||||
continue;
|
||||
}
|
||||
|
||||
_logger.LogDebug("Notifying for {ItemName}", item.Name);
|
||||
|
||||
// Send notification to each configured destination.
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.ItemAdded)
|
||||
.AddBaseItemData(item);
|
||||
|
||||
var itemType = item.GetType();
|
||||
await _webhookSender.SendNotification(NotificationType.ItemAdded, dataObject, itemType)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
// Remove item from queue.
|
||||
_itemProcessQueue.TryRemove(key, out _);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void AddItem(BaseItem item)
|
||||
{
|
||||
_itemProcessQueue.TryAdd(item.Id, new QueuedItemContainer(item.Id));
|
||||
_logger.LogDebug("Queued {ItemName} for notification", item.Name);
|
||||
_logger.LogDebug("Item {ItemName}", item.Name);
|
||||
|
||||
// Metadata not refreshed yet and under retry limit.
|
||||
if (item.ProviderIds.Keys.Count == 0 && container.RetryCount < MaxRetries)
|
||||
{
|
||||
_logger.LogDebug("Requeue {ItemName}, no provider ids", item.Name);
|
||||
container.RetryCount++;
|
||||
_itemProcessQueue.AddOrUpdate(key, container, (_, _) => container);
|
||||
continue;
|
||||
}
|
||||
|
||||
_logger.LogDebug("Notifying for {ItemName}", item.Name);
|
||||
|
||||
// Send notification to each configured destination.
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.ItemAdded)
|
||||
.AddBaseItemData(item);
|
||||
|
||||
var itemType = item.GetType();
|
||||
await _webhookSender.SendNotification(NotificationType.ItemAdded, dataObject, itemType)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
// Remove item from queue.
|
||||
_itemProcessQueue.TryRemove(key, out _);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void AddItem(BaseItem item)
|
||||
{
|
||||
_itemProcessQueue.TryAdd(item.Id, new QueuedItemContainer(item.Id));
|
||||
_logger.LogDebug("Queued {ItemName} for notification", item.Name);
|
||||
}
|
||||
}
|
||||
|
@ -4,65 +4,64 @@ using Jellyfin.Plugin.Webhook.Helpers;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Plugins;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers.ItemAddedNotifier
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers.ItemAddedNotifier;
|
||||
|
||||
/// <summary>
|
||||
/// Notifier when a library item is added.
|
||||
/// </summary>
|
||||
public class ItemAddedNotifierEntryPoint : IServerEntryPoint
|
||||
{
|
||||
private readonly IItemAddedManager _itemAddedManager;
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
|
||||
/// <summary>
|
||||
/// Notifier when a library item is added.
|
||||
/// Initializes a new instance of the <see cref="ItemAddedNotifierEntryPoint"/> class.
|
||||
/// </summary>
|
||||
public class ItemAddedNotifierEntryPoint : IServerEntryPoint
|
||||
/// <param name="itemAddedManager">Instance of the <see cref="IItemAddedManager"/> interface.</param>
|
||||
/// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
|
||||
public ItemAddedNotifierEntryPoint(
|
||||
IItemAddedManager itemAddedManager,
|
||||
ILibraryManager libraryManager)
|
||||
{
|
||||
private readonly IItemAddedManager _itemAddedManager;
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
_itemAddedManager = itemAddedManager;
|
||||
_libraryManager = libraryManager;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ItemAddedNotifierEntryPoint"/> class.
|
||||
/// </summary>
|
||||
/// <param name="itemAddedManager">Instance of the <see cref="IItemAddedManager"/> interface.</param>
|
||||
/// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
|
||||
public ItemAddedNotifierEntryPoint(
|
||||
IItemAddedManager itemAddedManager,
|
||||
ILibraryManager libraryManager)
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task RunAsync()
|
||||
{
|
||||
_libraryManager.ItemAdded += ItemAddedHandler;
|
||||
HandlebarsFunctionHelpers.RegisterHelpers();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose.
|
||||
/// </summary>
|
||||
/// <param name="disposing">Dispose all assets.</param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_itemAddedManager = itemAddedManager;
|
||||
_libraryManager = libraryManager;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task RunAsync()
|
||||
{
|
||||
_libraryManager.ItemAdded += ItemAddedHandler;
|
||||
HandlebarsFunctionHelpers.RegisterHelpers();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose.
|
||||
/// </summary>
|
||||
/// <param name="disposing">Dispose all assets.</param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_libraryManager.ItemAdded -= ItemAddedHandler;
|
||||
}
|
||||
}
|
||||
|
||||
private void ItemAddedHandler(object? sender, ItemChangeEventArgs itemChangeEventArgs)
|
||||
{
|
||||
// Never notify on virtual items.
|
||||
if (itemChangeEventArgs.Item.IsVirtualItem)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_itemAddedManager.AddItem(itemChangeEventArgs.Item);
|
||||
_libraryManager.ItemAdded -= ItemAddedHandler;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ItemAddedHandler(object? sender, ItemChangeEventArgs itemChangeEventArgs)
|
||||
{
|
||||
// Never notify on virtual items.
|
||||
if (itemChangeEventArgs.Item.IsVirtualItem)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_itemAddedManager.AddItem(itemChangeEventArgs.Item);
|
||||
}
|
||||
}
|
||||
|
@ -5,68 +5,67 @@ using System.Threading.Tasks;
|
||||
using MediaBrowser.Model.Globalization;
|
||||
using MediaBrowser.Model.Tasks;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers.ItemAddedNotifier
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers.ItemAddedNotifier;
|
||||
|
||||
/// <summary>
|
||||
/// Scheduled task that processes item added events.
|
||||
/// </summary>
|
||||
public class ItemAddedScheduledTask : IScheduledTask, IConfigurableScheduledTask
|
||||
{
|
||||
private const int RecheckIntervalSec = 30;
|
||||
private readonly IItemAddedManager _itemAddedManager;
|
||||
private readonly ILocalizationManager _localizationManager;
|
||||
|
||||
/// <summary>
|
||||
/// Scheduled task that processes item added events.
|
||||
/// Initializes a new instance of the <see cref="ItemAddedScheduledTask"/> class.
|
||||
/// </summary>
|
||||
public class ItemAddedScheduledTask : IScheduledTask, IConfigurableScheduledTask
|
||||
/// <param name="itemAddedManager">Instance of the <see cref="IItemAddedManager"/> interface.</param>
|
||||
/// <param name="localizationManager">Instance of the <see cref="ILocalizationManager"/> interface.</param>
|
||||
public ItemAddedScheduledTask(
|
||||
IItemAddedManager itemAddedManager,
|
||||
ILocalizationManager localizationManager)
|
||||
{
|
||||
private const int RecheckIntervalSec = 30;
|
||||
private readonly IItemAddedManager _itemAddedManager;
|
||||
private readonly ILocalizationManager _localizationManager;
|
||||
_itemAddedManager = itemAddedManager;
|
||||
_localizationManager = localizationManager;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ItemAddedScheduledTask"/> class.
|
||||
/// </summary>
|
||||
/// <param name="itemAddedManager">Instance of the <see cref="IItemAddedManager"/> interface.</param>
|
||||
/// <param name="localizationManager">Instance of the <see cref="ILocalizationManager"/> interface.</param>
|
||||
public ItemAddedScheduledTask(
|
||||
IItemAddedManager itemAddedManager,
|
||||
ILocalizationManager localizationManager)
|
||||
/// <inheritdoc />
|
||||
public string Name => "Webhook Item Added Notifier";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Key => "WebhookItemAdded";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Description => "Processes item added queue";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Category => _localizationManager.GetLocalizedString("TasksLibraryCategory");
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsHidden => false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsEnabled => true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsLogged => false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
return _itemAddedManager.ProcessItemsAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
_itemAddedManager = itemAddedManager;
|
||||
_localizationManager = localizationManager;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name => "Webhook Item Added Notifier";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Key => "WebhookItemAdded";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Description => "Processes item added queue";
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Category => _localizationManager.GetLocalizedString("TasksLibraryCategory");
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsHidden => false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsEnabled => true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsLogged => false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
|
||||
{
|
||||
return _itemAddedManager.ProcessItemsAsync();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
|
||||
{
|
||||
return new[]
|
||||
new TaskTriggerInfo
|
||||
{
|
||||
new TaskTriggerInfo
|
||||
{
|
||||
Type = TaskTriggerInfo.TriggerInterval,
|
||||
IntervalTicks = TimeSpan.FromSeconds(RecheckIntervalSec).Ticks
|
||||
}
|
||||
};
|
||||
}
|
||||
Type = TaskTriggerInfo.TriggerInterval,
|
||||
IntervalTicks = TimeSpan.FromSeconds(RecheckIntervalSec).Ticks
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -5,37 +5,36 @@ using Jellyfin.Plugin.Webhook.Helpers;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Events;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers;
|
||||
|
||||
/// <summary>
|
||||
/// Pending restart notifier.
|
||||
/// </summary>
|
||||
public class PendingRestartNotifier : IEventConsumer<PendingRestartEventArgs>
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
|
||||
/// <summary>
|
||||
/// Pending restart notifier.
|
||||
/// Initializes a new instance of the <see cref="PendingRestartNotifier"/> class.
|
||||
/// </summary>
|
||||
public class PendingRestartNotifier : IEventConsumer<PendingRestartEventArgs>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public PendingRestartNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PendingRestartNotifier"/> class.
|
||||
/// </summary>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public PendingRestartNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(PendingRestartEventArgs eventArgs)
|
||||
{
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.PendingRestart);
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(PendingRestartEventArgs eventArgs)
|
||||
{
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.PendingRestart);
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.PendingRestart, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
await _webhookSender.SendNotification(NotificationType.PendingRestart, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
@ -6,65 +6,64 @@ using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Events;
|
||||
using MediaBrowser.Controller.Library;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
{
|
||||
/// <summary>
|
||||
/// Playback progress notifier.
|
||||
/// </summary>
|
||||
public class PlaybackProgressNotifier : IEventConsumer<PlaybackProgressEventArgs>
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PlaybackProgressNotifier"/> class.
|
||||
/// </summary>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public PlaybackProgressNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
/// <summary>
|
||||
/// Playback progress notifier.
|
||||
/// </summary>
|
||||
public class PlaybackProgressNotifier : IEventConsumer<PlaybackProgressEventArgs>
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PlaybackProgressNotifier"/> class.
|
||||
/// </summary>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public PlaybackProgressNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(PlaybackProgressEventArgs eventArgs)
|
||||
{
|
||||
if (eventArgs.Item is null)
|
||||
{
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
return;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(PlaybackProgressEventArgs eventArgs)
|
||||
if (eventArgs.Item.IsThemeMedia)
|
||||
{
|
||||
if (eventArgs.Item is null)
|
||||
// Don't report theme song or local trailer playback.
|
||||
return;
|
||||
}
|
||||
|
||||
if (eventArgs.Users.Count == 0)
|
||||
{
|
||||
// No users in playback session.
|
||||
return;
|
||||
}
|
||||
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.PlaybackProgress)
|
||||
.AddBaseItemData(eventArgs.Item)
|
||||
.AddPlaybackProgressData(eventArgs);
|
||||
|
||||
foreach (var user in eventArgs.Users)
|
||||
{
|
||||
var userDataObject = new Dictionary<string, object>(dataObject)
|
||||
{
|
||||
return;
|
||||
}
|
||||
["NotificationUsername"] = user.Username,
|
||||
["UserId"] = user.Id
|
||||
};
|
||||
|
||||
if (eventArgs.Item.IsThemeMedia)
|
||||
{
|
||||
// Don't report theme song or local trailer playback.
|
||||
return;
|
||||
}
|
||||
|
||||
if (eventArgs.Users.Count == 0)
|
||||
{
|
||||
// No users in playback session.
|
||||
return;
|
||||
}
|
||||
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.PlaybackProgress)
|
||||
.AddBaseItemData(eventArgs.Item)
|
||||
.AddPlaybackProgressData(eventArgs);
|
||||
|
||||
foreach (var user in eventArgs.Users)
|
||||
{
|
||||
var userDataObject = new Dictionary<string, object>(dataObject)
|
||||
{
|
||||
["NotificationUsername"] = user.Username,
|
||||
["UserId"] = user.Id
|
||||
};
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.PlaybackProgress, userDataObject, eventArgs.Item.GetType())
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
await _webhookSender.SendNotification(NotificationType.PlaybackProgress, userDataObject, eventArgs.Item.GetType())
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,65 +6,64 @@ using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Events;
|
||||
using MediaBrowser.Controller.Library;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
{
|
||||
/// <summary>
|
||||
/// Playback start notifier.
|
||||
/// </summary>
|
||||
public class PlaybackStartNotifier : IEventConsumer<PlaybackStartEventArgs>
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PlaybackStartNotifier"/> class.
|
||||
/// </summary>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public PlaybackStartNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
/// <summary>
|
||||
/// Playback start notifier.
|
||||
/// </summary>
|
||||
public class PlaybackStartNotifier : IEventConsumer<PlaybackStartEventArgs>
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PlaybackStartNotifier"/> class.
|
||||
/// </summary>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public PlaybackStartNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(PlaybackStartEventArgs eventArgs)
|
||||
{
|
||||
if (eventArgs.Item is null)
|
||||
{
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
return;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(PlaybackStartEventArgs eventArgs)
|
||||
if (eventArgs.Item.IsThemeMedia)
|
||||
{
|
||||
if (eventArgs.Item is null)
|
||||
// Don't report theme song or local trailer playback.
|
||||
return;
|
||||
}
|
||||
|
||||
if (eventArgs.Users.Count == 0)
|
||||
{
|
||||
// No users in playback session.
|
||||
return;
|
||||
}
|
||||
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.PlaybackStart)
|
||||
.AddBaseItemData(eventArgs.Item)
|
||||
.AddPlaybackProgressData(eventArgs);
|
||||
|
||||
foreach (var user in eventArgs.Users)
|
||||
{
|
||||
var userDataObject = new Dictionary<string, object>(dataObject)
|
||||
{
|
||||
return;
|
||||
}
|
||||
["NotificationUsername"] = user.Username,
|
||||
["UserId"] = user.Id
|
||||
};
|
||||
|
||||
if (eventArgs.Item.IsThemeMedia)
|
||||
{
|
||||
// Don't report theme song or local trailer playback.
|
||||
return;
|
||||
}
|
||||
|
||||
if (eventArgs.Users.Count == 0)
|
||||
{
|
||||
// No users in playback session.
|
||||
return;
|
||||
}
|
||||
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.PlaybackStart)
|
||||
.AddBaseItemData(eventArgs.Item)
|
||||
.AddPlaybackProgressData(eventArgs);
|
||||
|
||||
foreach (var user in eventArgs.Users)
|
||||
{
|
||||
var userDataObject = new Dictionary<string, object>(dataObject)
|
||||
{
|
||||
["NotificationUsername"] = user.Username,
|
||||
["UserId"] = user.Id
|
||||
};
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.PlaybackStart, userDataObject, eventArgs.Item.GetType())
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
await _webhookSender.SendNotification(NotificationType.PlaybackStart, userDataObject, eventArgs.Item.GetType())
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,66 +6,65 @@ using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Events;
|
||||
using MediaBrowser.Controller.Library;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
{
|
||||
/// <summary>
|
||||
/// Playback stop notifier.
|
||||
/// </summary>
|
||||
public class PlaybackStopNotifier : IEventConsumer<PlaybackStopEventArgs>
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PlaybackStopNotifier"/> class.
|
||||
/// </summary>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public PlaybackStopNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
/// <summary>
|
||||
/// Playback stop notifier.
|
||||
/// </summary>
|
||||
public class PlaybackStopNotifier : IEventConsumer<PlaybackStopEventArgs>
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PlaybackStopNotifier"/> class.
|
||||
/// </summary>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public PlaybackStopNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(PlaybackStopEventArgs eventArgs)
|
||||
{
|
||||
if (eventArgs.Item is null)
|
||||
{
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
return;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(PlaybackStopEventArgs eventArgs)
|
||||
if (eventArgs.Item.IsThemeMedia)
|
||||
{
|
||||
if (eventArgs.Item is null)
|
||||
// Don't report theme song or local trailer playback.
|
||||
return;
|
||||
}
|
||||
|
||||
if (eventArgs.Users.Count == 0)
|
||||
{
|
||||
// No users in playback session.
|
||||
return;
|
||||
}
|
||||
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.PlaybackStop)
|
||||
.AddBaseItemData(eventArgs.Item)
|
||||
.AddPlaybackProgressData(eventArgs);
|
||||
dataObject[nameof(eventArgs.PlayedToCompletion)] = eventArgs.PlayedToCompletion;
|
||||
|
||||
foreach (var user in eventArgs.Users)
|
||||
{
|
||||
var userDataObject = new Dictionary<string, object>(dataObject)
|
||||
{
|
||||
return;
|
||||
}
|
||||
["NotificationUsername"] = user.Username,
|
||||
["UserId"] = user.Id
|
||||
};
|
||||
|
||||
if (eventArgs.Item.IsThemeMedia)
|
||||
{
|
||||
// Don't report theme song or local trailer playback.
|
||||
return;
|
||||
}
|
||||
|
||||
if (eventArgs.Users.Count == 0)
|
||||
{
|
||||
// No users in playback session.
|
||||
return;
|
||||
}
|
||||
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.PlaybackStop)
|
||||
.AddBaseItemData(eventArgs.Item)
|
||||
.AddPlaybackProgressData(eventArgs);
|
||||
dataObject[nameof(eventArgs.PlayedToCompletion)] = eventArgs.PlayedToCompletion;
|
||||
|
||||
foreach (var user in eventArgs.Users)
|
||||
{
|
||||
var userDataObject = new Dictionary<string, object>(dataObject)
|
||||
{
|
||||
["NotificationUsername"] = user.Username,
|
||||
["UserId"] = user.Id
|
||||
};
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.PlaybackStop, userDataObject, eventArgs.Item.GetType())
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
await _webhookSender.SendNotification(NotificationType.PlaybackStop, userDataObject, eventArgs.Item.GetType())
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,38 +5,37 @@ using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Events;
|
||||
using MediaBrowser.Controller.Events.Updates;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers;
|
||||
|
||||
/// <summary>
|
||||
/// Plugin installation cancelled.
|
||||
/// </summary>
|
||||
public class PluginInstallationCancelledNotifier : IEventConsumer<PluginInstallationCancelledEventArgs>
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
|
||||
/// <summary>
|
||||
/// Plugin installation cancelled.
|
||||
/// Initializes a new instance of the <see cref="PluginInstallationCancelledNotifier"/> class.
|
||||
/// </summary>
|
||||
public class PluginInstallationCancelledNotifier : IEventConsumer<PluginInstallationCancelledEventArgs>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public PluginInstallationCancelledNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PluginInstallationCancelledNotifier"/> class.
|
||||
/// </summary>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public PluginInstallationCancelledNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(PluginInstallationCancelledEventArgs eventArgs)
|
||||
{
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.PluginInstallationCancelled)
|
||||
.AddPluginInstallationInfo(eventArgs.Argument);
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(PluginInstallationCancelledEventArgs eventArgs)
|
||||
{
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.PluginInstallationCancelled)
|
||||
.AddPluginInstallationInfo(eventArgs.Argument);
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.PluginInstallationCancelled, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
await _webhookSender.SendNotification(NotificationType.PluginInstallationCancelled, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
@ -5,39 +5,38 @@ using MediaBrowser.Common.Updates;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Events;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers;
|
||||
|
||||
/// <summary>
|
||||
/// Plugin installation failed notifier.
|
||||
/// </summary>
|
||||
public class PluginInstallationFailedNotifier : IEventConsumer<InstallationFailedEventArgs>
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
|
||||
/// <summary>
|
||||
/// Plugin installation failed notifier.
|
||||
/// Initializes a new instance of the <see cref="PluginInstallationFailedNotifier"/> class.
|
||||
/// </summary>
|
||||
public class PluginInstallationFailedNotifier : IEventConsumer<InstallationFailedEventArgs>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public PluginInstallationFailedNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PluginInstallationFailedNotifier"/> class.
|
||||
/// </summary>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public PluginInstallationFailedNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(InstallationFailedEventArgs eventArgs)
|
||||
{
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.PluginInstallationFailed)
|
||||
.AddPluginInstallationInfo(eventArgs.InstallationInfo)
|
||||
.AddExceptionInfo(eventArgs.Exception);
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(InstallationFailedEventArgs eventArgs)
|
||||
{
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.PluginInstallationFailed)
|
||||
.AddPluginInstallationInfo(eventArgs.InstallationInfo)
|
||||
.AddExceptionInfo(eventArgs.Exception);
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.PluginInstallationFailed, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
await _webhookSender.SendNotification(NotificationType.PluginInstallationFailed, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
@ -5,38 +5,37 @@ using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Events;
|
||||
using MediaBrowser.Controller.Events.Updates;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers;
|
||||
|
||||
/// <summary>
|
||||
/// Plugin installed notifier.
|
||||
/// </summary>
|
||||
public class PluginInstalledNotifier : IEventConsumer<PluginInstalledEventArgs>
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
|
||||
/// <summary>
|
||||
/// Plugin installed notifier.
|
||||
/// Initializes a new instance of the <see cref="PluginInstalledNotifier"/> class.
|
||||
/// </summary>
|
||||
public class PluginInstalledNotifier : IEventConsumer<PluginInstalledEventArgs>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public PluginInstalledNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PluginInstalledNotifier"/> class.
|
||||
/// </summary>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public PluginInstalledNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(PluginInstalledEventArgs eventArgs)
|
||||
{
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.PluginInstalled)
|
||||
.AddPluginInstallationInfo(eventArgs.Argument);
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(PluginInstalledEventArgs eventArgs)
|
||||
{
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.PluginInstalled)
|
||||
.AddPluginInstallationInfo(eventArgs.Argument);
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.PluginInstalled, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
await _webhookSender.SendNotification(NotificationType.PluginInstalled, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
@ -5,38 +5,37 @@ using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Events;
|
||||
using MediaBrowser.Controller.Events.Updates;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers;
|
||||
|
||||
/// <summary>
|
||||
/// Plugin installing notifier.
|
||||
/// </summary>
|
||||
public class PluginInstallingNotifier : IEventConsumer<PluginInstallingEventArgs>
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
|
||||
/// <summary>
|
||||
/// Plugin installing notifier.
|
||||
/// Initializes a new instance of the <see cref="PluginInstallingNotifier"/> class.
|
||||
/// </summary>
|
||||
public class PluginInstallingNotifier : IEventConsumer<PluginInstallingEventArgs>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public PluginInstallingNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PluginInstallingNotifier"/> class.
|
||||
/// </summary>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public PluginInstallingNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(PluginInstallingEventArgs eventArgs)
|
||||
{
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.PluginInstalling)
|
||||
.AddPluginInstallationInfo(eventArgs.Argument);
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(PluginInstallingEventArgs eventArgs)
|
||||
{
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.PluginInstalling)
|
||||
.AddPluginInstallationInfo(eventArgs.Argument);
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.PluginInstalling, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
await _webhookSender.SendNotification(NotificationType.PluginInstalling, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
@ -5,42 +5,41 @@ using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Events;
|
||||
using MediaBrowser.Controller.Events.Updates;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers;
|
||||
|
||||
/// <summary>
|
||||
/// Plugin uninstalled notifier.
|
||||
/// </summary>
|
||||
public class PluginUninstalledNotifier : IEventConsumer<PluginUninstalledEventArgs>
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
|
||||
/// <summary>
|
||||
/// Plugin uninstalled notifier.
|
||||
/// Initializes a new instance of the <see cref="PluginUninstalledNotifier"/> class.
|
||||
/// </summary>
|
||||
public class PluginUninstalledNotifier : IEventConsumer<PluginUninstalledEventArgs>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public PluginUninstalledNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PluginUninstalledNotifier"/> class.
|
||||
/// </summary>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public PluginUninstalledNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(PluginUninstalledEventArgs eventArgs)
|
||||
{
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.PluginUninstalled);
|
||||
dataObject["PluginId"] = eventArgs.Argument.Id;
|
||||
dataObject["PluginName"] = eventArgs.Argument.Name;
|
||||
dataObject["PluginDescription"] = eventArgs.Argument.Description;
|
||||
dataObject["PluginVersion"] = eventArgs.Argument.Version;
|
||||
dataObject["PluginStatus"] = eventArgs.Argument.Status;
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(PluginUninstalledEventArgs eventArgs)
|
||||
{
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.PluginUninstalled);
|
||||
dataObject["PluginId"] = eventArgs.Argument.Id;
|
||||
dataObject["PluginName"] = eventArgs.Argument.Name;
|
||||
dataObject["PluginDescription"] = eventArgs.Argument.Description;
|
||||
dataObject["PluginVersion"] = eventArgs.Argument.Version;
|
||||
dataObject["PluginStatus"] = eventArgs.Argument.Status;
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.PluginUninstalled, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
await _webhookSender.SendNotification(NotificationType.PluginUninstalled, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
@ -5,38 +5,37 @@ using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Events;
|
||||
using MediaBrowser.Controller.Events.Updates;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers;
|
||||
|
||||
/// <summary>
|
||||
/// Plugin updated notifier.
|
||||
/// </summary>
|
||||
public class PluginUpdatedNotifier : IEventConsumer<PluginUpdatedEventArgs>
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
|
||||
/// <summary>
|
||||
/// Plugin updated notifier.
|
||||
/// Initializes a new instance of the <see cref="PluginUpdatedNotifier"/> class.
|
||||
/// </summary>
|
||||
public class PluginUpdatedNotifier : IEventConsumer<PluginUpdatedEventArgs>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public PluginUpdatedNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PluginUpdatedNotifier"/> class.
|
||||
/// </summary>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public PluginUpdatedNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(PluginUpdatedEventArgs eventArgs)
|
||||
{
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.PluginUpdated)
|
||||
.AddPluginInstallationInfo(eventArgs.Argument);
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(PluginUpdatedEventArgs eventArgs)
|
||||
{
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.PluginUpdated)
|
||||
.AddPluginInstallationInfo(eventArgs.Argument);
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.PluginUpdated, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
await _webhookSender.SendNotification(NotificationType.PluginUpdated, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
@ -5,44 +5,43 @@ using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Events;
|
||||
using MediaBrowser.Controller.Events.Session;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers;
|
||||
|
||||
/// <summary>
|
||||
/// Session start notifier.
|
||||
/// </summary>
|
||||
public class SessionStartNotifier : IEventConsumer<SessionStartedEventArgs>
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
|
||||
/// <summary>
|
||||
/// Session start notifier.
|
||||
/// Initializes a new instance of the <see cref="SessionStartNotifier"/> class.
|
||||
/// </summary>
|
||||
public class SessionStartNotifier : IEventConsumer<SessionStartedEventArgs>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public SessionStartNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SessionStartNotifier"/> class.
|
||||
/// </summary>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public SessionStartNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(SessionStartedEventArgs eventArgs)
|
||||
{
|
||||
if (eventArgs.Argument is null)
|
||||
{
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
return;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(SessionStartedEventArgs eventArgs)
|
||||
{
|
||||
if (eventArgs.Argument is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.SessionStart)
|
||||
.AddSessionInfoData(eventArgs.Argument)
|
||||
.AddBaseItemData(eventArgs.Argument.FullNowPlayingItem);
|
||||
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.SessionStart)
|
||||
.AddSessionInfoData(eventArgs.Argument)
|
||||
.AddBaseItemData(eventArgs.Argument.FullNowPlayingItem);
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.SessionStart, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
await _webhookSender.SendNotification(NotificationType.SessionStart, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
@ -5,42 +5,41 @@ using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Events;
|
||||
using MediaBrowser.Controller.Subtitles;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers;
|
||||
|
||||
/// <summary>
|
||||
/// Subtitle download failure notifier.
|
||||
/// </summary>
|
||||
public class SubtitleDownloadFailureNotifier : IEventConsumer<SubtitleDownloadFailureEventArgs>
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
|
||||
/// <summary>
|
||||
/// Subtitle download failure notifier.
|
||||
/// Initializes a new instance of the <see cref="SubtitleDownloadFailureNotifier"/> class.
|
||||
/// </summary>
|
||||
public class SubtitleDownloadFailureNotifier : IEventConsumer<SubtitleDownloadFailureEventArgs>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public SubtitleDownloadFailureNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SubtitleDownloadFailureNotifier"/> class.
|
||||
/// </summary>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public SubtitleDownloadFailureNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(SubtitleDownloadFailureEventArgs eventArgs)
|
||||
{
|
||||
if (eventArgs.Item is null)
|
||||
{
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
return;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(SubtitleDownloadFailureEventArgs eventArgs)
|
||||
{
|
||||
if (eventArgs.Item is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.SubtitleDownloadFailure)
|
||||
.AddBaseItemData(eventArgs.Item);
|
||||
await _webhookSender.SendNotification(NotificationType.SubtitleDownloadFailure, dataObject, eventArgs.Item.GetType())
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.SubtitleDownloadFailure)
|
||||
.AddBaseItemData(eventArgs.Item);
|
||||
await _webhookSender.SendNotification(NotificationType.SubtitleDownloadFailure, dataObject, eventArgs.Item.GetType())
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
@ -5,50 +5,49 @@ using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Events;
|
||||
using MediaBrowser.Model.Tasks;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers;
|
||||
|
||||
/// <summary>
|
||||
/// Task completed notifier.
|
||||
/// </summary>
|
||||
public class TaskCompletedNotifier : IEventConsumer<TaskCompletionEventArgs>
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
|
||||
/// <summary>
|
||||
/// Task completed notifier.
|
||||
/// Initializes a new instance of the <see cref="TaskCompletedNotifier"/> class.
|
||||
/// </summary>
|
||||
public class TaskCompletedNotifier : IEventConsumer<TaskCompletionEventArgs>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public TaskCompletedNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TaskCompletedNotifier"/> class.
|
||||
/// </summary>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public TaskCompletedNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(TaskCompletionEventArgs eventArgs)
|
||||
{
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.TaskCompleted);
|
||||
dataObject["TaskId"] = eventArgs.Task.Id;
|
||||
dataObject["TaskName"] = eventArgs.Task.Name;
|
||||
dataObject["TaskDescription"] = eventArgs.Task.Description;
|
||||
dataObject["TaskCategory"] = eventArgs.Task.Category;
|
||||
dataObject["TaskState"] = eventArgs.Task.State.ToString();
|
||||
dataObject["ResultId"] = eventArgs.Result.Id;
|
||||
dataObject["ResultKey"] = eventArgs.Result.Key;
|
||||
dataObject["ResultName"] = eventArgs.Result.Name;
|
||||
dataObject["ResultStatus"] = eventArgs.Result.Status.ToString();
|
||||
dataObject["StartTime"] = eventArgs.Result.StartTimeUtc;
|
||||
dataObject["EndTime"] = eventArgs.Result.EndTimeUtc;
|
||||
dataObject["ResultErrorMessage"] = eventArgs.Result.ErrorMessage;
|
||||
dataObject["ResultLongErrorMessage"] = eventArgs.Result.LongErrorMessage;
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(TaskCompletionEventArgs eventArgs)
|
||||
{
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.TaskCompleted);
|
||||
dataObject["TaskId"] = eventArgs.Task.Id;
|
||||
dataObject["TaskName"] = eventArgs.Task.Name;
|
||||
dataObject["TaskDescription"] = eventArgs.Task.Description;
|
||||
dataObject["TaskCategory"] = eventArgs.Task.Category;
|
||||
dataObject["TaskState"] = eventArgs.Task.State.ToString();
|
||||
dataObject["ResultId"] = eventArgs.Result.Id;
|
||||
dataObject["ResultKey"] = eventArgs.Result.Key;
|
||||
dataObject["ResultName"] = eventArgs.Result.Name;
|
||||
dataObject["ResultStatus"] = eventArgs.Result.Status.ToString();
|
||||
dataObject["StartTime"] = eventArgs.Result.StartTimeUtc;
|
||||
dataObject["EndTime"] = eventArgs.Result.EndTimeUtc;
|
||||
dataObject["ResultErrorMessage"] = eventArgs.Result.ErrorMessage;
|
||||
dataObject["ResultLongErrorMessage"] = eventArgs.Result.LongErrorMessage;
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.TaskCompleted, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
await _webhookSender.SendNotification(NotificationType.TaskCompleted, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
@ -5,38 +5,37 @@ using Jellyfin.Plugin.Webhook.Helpers;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Events;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers;
|
||||
|
||||
/// <summary>
|
||||
/// User created notifier.
|
||||
/// </summary>
|
||||
public class UserCreatedNotifier : IEventConsumer<UserCreatedEventArgs>
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
|
||||
/// <summary>
|
||||
/// User created notifier.
|
||||
/// Initializes a new instance of the <see cref="UserCreatedNotifier"/> class.
|
||||
/// </summary>
|
||||
public class UserCreatedNotifier : IEventConsumer<UserCreatedEventArgs>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public UserCreatedNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UserCreatedNotifier"/> class.
|
||||
/// </summary>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public UserCreatedNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(UserCreatedEventArgs eventArgs)
|
||||
{
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.UserCreated)
|
||||
.AddUserData(eventArgs.Argument);
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(UserCreatedEventArgs eventArgs)
|
||||
{
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.UserCreated)
|
||||
.AddUserData(eventArgs.Argument);
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.UserCreated, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
await _webhookSender.SendNotification(NotificationType.UserCreated, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
@ -7,104 +7,103 @@ using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Plugins;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers.UserDataSavedNotifier
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers.UserDataSavedNotifier;
|
||||
|
||||
/// <summary>
|
||||
/// User data saved notifier.
|
||||
/// </summary>
|
||||
public class UserDataSavedNotifierEntryPoint : IServerEntryPoint
|
||||
{
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IUserDataManager _userDataManager;
|
||||
private readonly IUserManager _userManager;
|
||||
private readonly ILogger<UserDataSavedNotifierEntryPoint> _logger;
|
||||
|
||||
/// <summary>
|
||||
/// User data saved notifier.
|
||||
/// Initializes a new instance of the <see cref="UserDataSavedNotifierEntryPoint"/> class.
|
||||
/// </summary>
|
||||
public class UserDataSavedNotifierEntryPoint : IServerEntryPoint
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
/// <param name="userDataManager">Instance of the <see cref="IUserDataManager"/> interface.</param>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="logger">Instance of the <see cref="ILogger{UserDataChangedNotifierEntryPoint}"/> interface.</param>
|
||||
/// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
|
||||
public UserDataSavedNotifierEntryPoint(
|
||||
IWebhookSender webhookSender,
|
||||
IServerApplicationHost applicationHost,
|
||||
IUserDataManager userDataManager,
|
||||
ILogger<UserDataSavedNotifierEntryPoint> logger,
|
||||
IUserManager userManager)
|
||||
{
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IUserDataManager _userDataManager;
|
||||
private readonly IUserManager _userManager;
|
||||
private readonly ILogger<UserDataSavedNotifierEntryPoint> _logger;
|
||||
_userDataManager = userDataManager;
|
||||
_logger = logger;
|
||||
_userManager = userManager;
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UserDataSavedNotifierEntryPoint"/> class.
|
||||
/// </summary>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
/// <param name="userDataManager">Instance of the <see cref="IUserDataManager"/> interface.</param>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="logger">Instance of the <see cref="ILogger{UserDataChangedNotifierEntryPoint}"/> interface.</param>
|
||||
/// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
|
||||
public UserDataSavedNotifierEntryPoint(
|
||||
IWebhookSender webhookSender,
|
||||
IServerApplicationHost applicationHost,
|
||||
IUserDataManager userDataManager,
|
||||
ILogger<UserDataSavedNotifierEntryPoint> logger,
|
||||
IUserManager userManager)
|
||||
/// <inheritdoc />
|
||||
public Task RunAsync()
|
||||
{
|
||||
_userDataManager.UserDataSaved += UserDataSavedHandler;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose.
|
||||
/// </summary>
|
||||
/// <param name="disposing">Dispose all assets.</param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_userDataManager = userDataManager;
|
||||
_logger = logger;
|
||||
_userManager = userManager;
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
_userDataManager.UserDataSaved -= UserDataSavedHandler;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task RunAsync()
|
||||
private async void UserDataSavedHandler(object? sender, UserDataSaveEventArgs eventArgs)
|
||||
{
|
||||
try
|
||||
{
|
||||
_userDataManager.UserDataSaved += UserDataSavedHandler;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose.
|
||||
/// </summary>
|
||||
/// <param name="disposing">Dispose all assets.</param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
if (eventArgs.Item is null)
|
||||
{
|
||||
_userDataManager.UserDataSaved -= UserDataSavedHandler;
|
||||
return;
|
||||
}
|
||||
|
||||
if (eventArgs.Item.IsThemeMedia)
|
||||
{
|
||||
// Don't report theme song or local trailer playback.
|
||||
return;
|
||||
}
|
||||
|
||||
var user = _userManager.GetUserById(eventArgs.UserId);
|
||||
if (user is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.UserDataSaved)
|
||||
.AddBaseItemData(eventArgs.Item)
|
||||
.AddUserItemData(eventArgs.UserData);
|
||||
|
||||
dataObject["SaveReason"] = eventArgs.SaveReason.ToString();
|
||||
dataObject["NotificationUsername"] = user.Username;
|
||||
dataObject["UserId"] = user.Id;
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.UserDataSaved, dataObject, eventArgs.Item.GetType())
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async void UserDataSavedHandler(object? sender, UserDataSaveEventArgs eventArgs)
|
||||
catch (Exception ex)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (eventArgs.Item is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (eventArgs.Item.IsThemeMedia)
|
||||
{
|
||||
// Don't report theme song or local trailer playback.
|
||||
return;
|
||||
}
|
||||
|
||||
var user = _userManager.GetUserById(eventArgs.UserId);
|
||||
if (user is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.UserDataSaved)
|
||||
.AddBaseItemData(eventArgs.Item)
|
||||
.AddUserItemData(eventArgs.UserData);
|
||||
|
||||
dataObject["SaveReason"] = eventArgs.SaveReason.ToString();
|
||||
dataObject["NotificationUsername"] = user.Username;
|
||||
dataObject["UserId"] = user.Id;
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.UserDataSaved, dataObject, eventArgs.Item.GetType())
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Unable to send notification");
|
||||
}
|
||||
_logger.LogWarning(ex, "Unable to send notification");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,38 +5,37 @@ using Jellyfin.Plugin.Webhook.Helpers;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Events;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers;
|
||||
|
||||
/// <summary>
|
||||
/// User deleted notifier.
|
||||
/// </summary>
|
||||
public class UserDeletedNotifier : IEventConsumer<UserDeletedEventArgs>
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
|
||||
/// <summary>
|
||||
/// User deleted notifier.
|
||||
/// Initializes a new instance of the <see cref="UserDeletedNotifier"/> class.
|
||||
/// </summary>
|
||||
public class UserDeletedNotifier : IEventConsumer<UserDeletedEventArgs>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public UserDeletedNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UserDeletedNotifier"/> class.
|
||||
/// </summary>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public UserDeletedNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(UserDeletedEventArgs eventArgs)
|
||||
{
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.UserDeleted)
|
||||
.AddUserData(eventArgs.Argument);
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(UserDeletedEventArgs eventArgs)
|
||||
{
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.UserDeleted)
|
||||
.AddUserData(eventArgs.Argument);
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.UserDeleted, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
await _webhookSender.SendNotification(NotificationType.UserDeleted, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
@ -5,38 +5,37 @@ using Jellyfin.Plugin.Webhook.Helpers;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Events;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers;
|
||||
|
||||
/// <summary>
|
||||
/// User locked out notifier.
|
||||
/// </summary>
|
||||
public class UserLockedOutNotifier : IEventConsumer<UserLockedOutEventArgs>
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
|
||||
/// <summary>
|
||||
/// User locked out notifier.
|
||||
/// Initializes a new instance of the <see cref="UserLockedOutNotifier"/> class.
|
||||
/// </summary>
|
||||
public class UserLockedOutNotifier : IEventConsumer<UserLockedOutEventArgs>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public UserLockedOutNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UserLockedOutNotifier"/> class.
|
||||
/// </summary>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public UserLockedOutNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(UserLockedOutEventArgs eventArgs)
|
||||
{
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.UserLockedOut)
|
||||
.AddUserData(eventArgs.Argument);
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(UserLockedOutEventArgs eventArgs)
|
||||
{
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.UserLockedOut)
|
||||
.AddUserData(eventArgs.Argument);
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.UserLockedOut, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
await _webhookSender.SendNotification(NotificationType.UserLockedOut, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
@ -5,38 +5,37 @@ using Jellyfin.Plugin.Webhook.Helpers;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Events;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers;
|
||||
|
||||
/// <summary>
|
||||
/// User password changed notifier.
|
||||
/// </summary>
|
||||
public class UserPasswordChangedNotifier : IEventConsumer<UserPasswordChangedEventArgs>
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
|
||||
/// <summary>
|
||||
/// User password changed notifier.
|
||||
/// Initializes a new instance of the <see cref="UserPasswordChangedNotifier"/> class.
|
||||
/// </summary>
|
||||
public class UserPasswordChangedNotifier : IEventConsumer<UserPasswordChangedEventArgs>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public UserPasswordChangedNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UserPasswordChangedNotifier"/> class.
|
||||
/// </summary>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public UserPasswordChangedNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(UserPasswordChangedEventArgs eventArgs)
|
||||
{
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.UserPasswordChanged)
|
||||
.AddUserData(eventArgs.Argument);
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(UserPasswordChangedEventArgs eventArgs)
|
||||
{
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.UserPasswordChanged)
|
||||
.AddUserData(eventArgs.Argument);
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.UserPasswordChanged, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
await _webhookSender.SendNotification(NotificationType.UserPasswordChanged, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
@ -5,38 +5,37 @@ using Jellyfin.Plugin.Webhook.Helpers;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Events;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
namespace Jellyfin.Plugin.Webhook.Notifiers;
|
||||
|
||||
/// <summary>
|
||||
/// User updated notifier.
|
||||
/// </summary>
|
||||
public class UserUpdatedNotifier : IEventConsumer<UserUpdatedEventArgs>
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
|
||||
/// <summary>
|
||||
/// User updated notifier.
|
||||
/// Initializes a new instance of the <see cref="UserUpdatedNotifier"/> class.
|
||||
/// </summary>
|
||||
public class UserUpdatedNotifier : IEventConsumer<UserUpdatedEventArgs>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public UserUpdatedNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
private readonly IServerApplicationHost _applicationHost;
|
||||
private readonly IWebhookSender _webhookSender;
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UserUpdatedNotifier"/> class.
|
||||
/// </summary>
|
||||
/// <param name="applicationHost">Instance of the <see cref="IServerApplicationHost"/> interface.</param>
|
||||
/// <param name="webhookSender">Instance of the <see cref="IWebhookSender"/> interface.</param>
|
||||
public UserUpdatedNotifier(
|
||||
IServerApplicationHost applicationHost,
|
||||
IWebhookSender webhookSender)
|
||||
{
|
||||
_applicationHost = applicationHost;
|
||||
_webhookSender = webhookSender;
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(UserUpdatedEventArgs eventArgs)
|
||||
{
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.UserUpdated)
|
||||
.AddUserData(eventArgs.Argument);
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(UserUpdatedEventArgs eventArgs)
|
||||
{
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.UserUpdated)
|
||||
.AddUserData(eventArgs.Argument);
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.UserUpdated, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
await _webhookSender.SendNotification(NotificationType.UserUpdated, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
@ -25,65 +25,64 @@ using MediaBrowser.Controller.Subtitles;
|
||||
using MediaBrowser.Model.Tasks;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook
|
||||
namespace Jellyfin.Plugin.Webhook;
|
||||
|
||||
/// <summary>
|
||||
/// Register webhook services.
|
||||
/// </summary>
|
||||
public class PluginServiceRegistrator : IPluginServiceRegistrator
|
||||
{
|
||||
/// <summary>
|
||||
/// Register webhook services.
|
||||
/// </summary>
|
||||
public class PluginServiceRegistrator : IPluginServiceRegistrator
|
||||
/// <inheritdoc />
|
||||
public void RegisterServices(IServiceCollection serviceCollection)
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public void RegisterServices(IServiceCollection serviceCollection)
|
||||
{
|
||||
serviceCollection.AddScoped<IWebhookClient<DiscordOption>, DiscordClient>();
|
||||
serviceCollection.AddScoped<IWebhookClient<GenericOption>, GenericClient>();
|
||||
serviceCollection.AddScoped<IWebhookClient<GenericFormOption>, GenericFormClient>();
|
||||
serviceCollection.AddScoped<IWebhookClient<GotifyOption>, GotifyClient>();
|
||||
serviceCollection.AddScoped<IWebhookClient<PushbulletOption>, PushbulletClient>();
|
||||
serviceCollection.AddScoped<IWebhookClient<PushoverOption>, PushoverClient>();
|
||||
serviceCollection.AddScoped<IWebhookClient<SlackOption>, SlackClient>();
|
||||
serviceCollection.AddScoped<IWebhookClient<SmtpOption>, SmtpClient>();
|
||||
serviceCollection.AddScoped<IWebhookClient<MqttOption>, MqttClient>();
|
||||
serviceCollection.AddScoped<IWebhookClient<DiscordOption>, DiscordClient>();
|
||||
serviceCollection.AddScoped<IWebhookClient<GenericOption>, GenericClient>();
|
||||
serviceCollection.AddScoped<IWebhookClient<GenericFormOption>, GenericFormClient>();
|
||||
serviceCollection.AddScoped<IWebhookClient<GotifyOption>, GotifyClient>();
|
||||
serviceCollection.AddScoped<IWebhookClient<PushbulletOption>, PushbulletClient>();
|
||||
serviceCollection.AddScoped<IWebhookClient<PushoverOption>, PushoverClient>();
|
||||
serviceCollection.AddScoped<IWebhookClient<SlackOption>, SlackClient>();
|
||||
serviceCollection.AddScoped<IWebhookClient<SmtpOption>, SmtpClient>();
|
||||
serviceCollection.AddScoped<IWebhookClient<MqttOption>, MqttClient>();
|
||||
|
||||
// Register sender.
|
||||
serviceCollection.AddScoped<IWebhookSender, WebhookSender>();
|
||||
// Register sender.
|
||||
serviceCollection.AddScoped<IWebhookSender, WebhookSender>();
|
||||
|
||||
// Register MqttClients
|
||||
serviceCollection.AddSingleton<IMqttClients, MqttClients>();
|
||||
// Register MqttClients
|
||||
serviceCollection.AddSingleton<IMqttClients, MqttClients>();
|
||||
|
||||
/*-- Register event consumers. --*/
|
||||
// Library consumers.
|
||||
serviceCollection.AddScoped<IEventConsumer<SubtitleDownloadFailureEventArgs>, SubtitleDownloadFailureNotifier>();
|
||||
serviceCollection.AddSingleton<IItemAddedManager, ItemAddedManager>();
|
||||
/*-- Register event consumers. --*/
|
||||
// Library consumers.
|
||||
serviceCollection.AddScoped<IEventConsumer<SubtitleDownloadFailureEventArgs>, SubtitleDownloadFailureNotifier>();
|
||||
serviceCollection.AddSingleton<IItemAddedManager, ItemAddedManager>();
|
||||
|
||||
// Security consumers.
|
||||
serviceCollection.AddScoped<IEventConsumer<GenericEventArgs<AuthenticationRequest>>, AuthenticationFailureNotifier>();
|
||||
serviceCollection.AddScoped<IEventConsumer<GenericEventArgs<AuthenticationResult>>, AuthenticationSuccessNotifier>();
|
||||
// Security consumers.
|
||||
serviceCollection.AddScoped<IEventConsumer<GenericEventArgs<AuthenticationRequest>>, AuthenticationFailureNotifier>();
|
||||
serviceCollection.AddScoped<IEventConsumer<GenericEventArgs<AuthenticationResult>>, AuthenticationSuccessNotifier>();
|
||||
|
||||
// Session consumers.
|
||||
serviceCollection.AddScoped<IEventConsumer<PlaybackStartEventArgs>, PlaybackStartNotifier>();
|
||||
serviceCollection.AddScoped<IEventConsumer<PlaybackStopEventArgs>, PlaybackStopNotifier>();
|
||||
serviceCollection.AddScoped<IEventConsumer<PlaybackProgressEventArgs>, PlaybackProgressNotifier>();
|
||||
serviceCollection.AddScoped<IEventConsumer<SessionStartedEventArgs>, SessionStartNotifier>();
|
||||
// Session consumers.
|
||||
serviceCollection.AddScoped<IEventConsumer<PlaybackStartEventArgs>, PlaybackStartNotifier>();
|
||||
serviceCollection.AddScoped<IEventConsumer<PlaybackStopEventArgs>, PlaybackStopNotifier>();
|
||||
serviceCollection.AddScoped<IEventConsumer<PlaybackProgressEventArgs>, PlaybackProgressNotifier>();
|
||||
serviceCollection.AddScoped<IEventConsumer<SessionStartedEventArgs>, SessionStartNotifier>();
|
||||
|
||||
// System consumers.
|
||||
serviceCollection.AddScoped<IEventConsumer<PendingRestartEventArgs>, PendingRestartNotifier>();
|
||||
serviceCollection.AddScoped<IEventConsumer<TaskCompletionEventArgs>, TaskCompletedNotifier>();
|
||||
// System consumers.
|
||||
serviceCollection.AddScoped<IEventConsumer<PendingRestartEventArgs>, PendingRestartNotifier>();
|
||||
serviceCollection.AddScoped<IEventConsumer<TaskCompletionEventArgs>, TaskCompletedNotifier>();
|
||||
|
||||
// Update consumers.
|
||||
serviceCollection.AddScoped<IEventConsumer<PluginInstallationCancelledEventArgs>, PluginInstallationCancelledNotifier>();
|
||||
serviceCollection.AddScoped<IEventConsumer<InstallationFailedEventArgs>, PluginInstallationFailedNotifier>();
|
||||
serviceCollection.AddScoped<IEventConsumer<PluginInstalledEventArgs>, PluginInstalledNotifier>();
|
||||
serviceCollection.AddScoped<IEventConsumer<PluginInstallingEventArgs>, PluginInstallingNotifier>();
|
||||
serviceCollection.AddScoped<IEventConsumer<PluginUninstalledEventArgs>, PluginUninstalledNotifier>();
|
||||
serviceCollection.AddScoped<IEventConsumer<PluginUpdatedEventArgs>, PluginUpdatedNotifier>();
|
||||
// Update consumers.
|
||||
serviceCollection.AddScoped<IEventConsumer<PluginInstallationCancelledEventArgs>, PluginInstallationCancelledNotifier>();
|
||||
serviceCollection.AddScoped<IEventConsumer<InstallationFailedEventArgs>, PluginInstallationFailedNotifier>();
|
||||
serviceCollection.AddScoped<IEventConsumer<PluginInstalledEventArgs>, PluginInstalledNotifier>();
|
||||
serviceCollection.AddScoped<IEventConsumer<PluginInstallingEventArgs>, PluginInstallingNotifier>();
|
||||
serviceCollection.AddScoped<IEventConsumer<PluginUninstalledEventArgs>, PluginUninstalledNotifier>();
|
||||
serviceCollection.AddScoped<IEventConsumer<PluginUpdatedEventArgs>, PluginUpdatedNotifier>();
|
||||
|
||||
// User consumers.
|
||||
serviceCollection.AddScoped<IEventConsumer<UserCreatedEventArgs>, UserCreatedNotifier>();
|
||||
serviceCollection.AddScoped<IEventConsumer<UserDeletedEventArgs>, UserDeletedNotifier>();
|
||||
serviceCollection.AddScoped<IEventConsumer<UserLockedOutEventArgs>, UserLockedOutNotifier>();
|
||||
serviceCollection.AddScoped<IEventConsumer<UserPasswordChangedEventArgs>, UserPasswordChangedNotifier>();
|
||||
serviceCollection.AddScoped<IEventConsumer<UserUpdatedEventArgs>, UserUpdatedNotifier>();
|
||||
}
|
||||
// User consumers.
|
||||
serviceCollection.AddScoped<IEventConsumer<UserCreatedEventArgs>, UserCreatedNotifier>();
|
||||
serviceCollection.AddScoped<IEventConsumer<UserDeletedEventArgs>, UserDeletedNotifier>();
|
||||
serviceCollection.AddScoped<IEventConsumer<UserLockedOutEventArgs>, UserLockedOutNotifier>();
|
||||
serviceCollection.AddScoped<IEventConsumer<UserPasswordChangedEventArgs>, UserPasswordChangedNotifier>();
|
||||
serviceCollection.AddScoped<IEventConsumer<UserUpdatedEventArgs>, UserUpdatedNotifier>();
|
||||
}
|
||||
}
|
||||
|
@ -6,55 +6,54 @@ using MediaBrowser.Common.Plugins;
|
||||
using MediaBrowser.Model.Plugins;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook
|
||||
namespace Jellyfin.Plugin.Webhook;
|
||||
|
||||
/// <summary>
|
||||
/// Plugin entrypoint.
|
||||
/// </summary>
|
||||
public class WebhookPlugin : BasePlugin<PluginConfiguration>, IHasWebPages
|
||||
{
|
||||
private readonly Guid _id = new("71552A5A-5C5C-4350-A2AE-EBE451A30173");
|
||||
|
||||
/// <summary>
|
||||
/// Plugin entrypoint.
|
||||
/// Initializes a new instance of the <see cref="WebhookPlugin"/> class.
|
||||
/// </summary>
|
||||
public class WebhookPlugin : BasePlugin<PluginConfiguration>, IHasWebPages
|
||||
/// <param name="applicationPaths">Instance of the <see cref="IApplicationPaths"/> interface.</param>
|
||||
/// <param name="xmlSerializer">Instance of the <see cref="IXmlSerializer"/> interface.</param>
|
||||
public WebhookPlugin(IApplicationPaths applicationPaths, IXmlSerializer xmlSerializer)
|
||||
: base(applicationPaths, xmlSerializer)
|
||||
{
|
||||
private readonly Guid _id = new ("71552A5A-5C5C-4350-A2AE-EBE451A30173");
|
||||
Instance = this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WebhookPlugin"/> class.
|
||||
/// </summary>
|
||||
/// <param name="applicationPaths">Instance of the <see cref="IApplicationPaths"/> interface.</param>
|
||||
/// <param name="xmlSerializer">Instance of the <see cref="IXmlSerializer"/> interface.</param>
|
||||
public WebhookPlugin(IApplicationPaths applicationPaths, IXmlSerializer xmlSerializer)
|
||||
: base(applicationPaths, xmlSerializer)
|
||||
/// <summary>
|
||||
/// Gets current plugin instance.
|
||||
/// </summary>
|
||||
public static WebhookPlugin? Instance { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Guid Id => _id;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Name => "Webhook";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Sends notifications to various services via webhooks.";
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<PluginPageInfo> GetPages()
|
||||
{
|
||||
var prefix = GetType().Namespace;
|
||||
yield return new PluginPageInfo
|
||||
{
|
||||
Instance = this;
|
||||
}
|
||||
Name = Name,
|
||||
EmbeddedResourcePath = prefix + ".Configuration.Web.config.html"
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Gets current plugin instance.
|
||||
/// </summary>
|
||||
public static WebhookPlugin? Instance { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Guid Id => _id;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Name => "Webhook";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Description => "Sends notifications to various services via webhooks.";
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<PluginPageInfo> GetPages()
|
||||
yield return new PluginPageInfo
|
||||
{
|
||||
var prefix = GetType().Namespace;
|
||||
yield return new PluginPageInfo
|
||||
{
|
||||
Name = Name,
|
||||
EmbeddedResourcePath = prefix + ".Configuration.Web.config.html"
|
||||
};
|
||||
|
||||
yield return new PluginPageInfo
|
||||
{
|
||||
Name = $"{Name}.js",
|
||||
EmbeddedResourcePath = prefix + ".Configuration.Web.config.js"
|
||||
};
|
||||
}
|
||||
Name = $"{Name}.js",
|
||||
EmbeddedResourcePath = prefix + ".Configuration.Web.config.js"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -18,175 +18,174 @@ using MediaBrowser.Controller.Entities.Movies;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook
|
||||
namespace Jellyfin.Plugin.Webhook;
|
||||
|
||||
/// <inheritdoc />
|
||||
public class WebhookSender : IWebhookSender
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public class WebhookSender : IWebhookSender
|
||||
private readonly ILogger<WebhookSender> _logger;
|
||||
private readonly IWebhookClient<DiscordOption> _discordClient;
|
||||
private readonly IWebhookClient<GenericOption> _genericClient;
|
||||
private readonly IWebhookClient<GenericFormOption> _genericFormClient;
|
||||
private readonly IWebhookClient<GotifyOption> _gotifyClient;
|
||||
private readonly IWebhookClient<PushbulletOption> _pushbulletClient;
|
||||
private readonly IWebhookClient<PushoverOption> _pushoverClient;
|
||||
private readonly IWebhookClient<SlackOption> _slackClient;
|
||||
private readonly IWebhookClient<SmtpOption> _smtpClient;
|
||||
private readonly IWebhookClient<MqttOption> _mqttClient;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WebhookSender"/> class.
|
||||
/// </summary>
|
||||
/// <param name="logger">Instance of the <see cref="ILogger{WebhookSender}"/> interface.</param>
|
||||
/// <param name="discordClient">Instance of <see cref="IWebhookClient{DiscordOption}"/>.</param>
|
||||
/// /// <param name="genericClient">Instance of the <see cref="IWebhookClient{GenericOption}"/>.</param>
|
||||
/// <param name="genericFormClient">Instance of the <see cref="IWebhookClient{GenericFormOption}"/>.</param>
|
||||
/// <param name="gotifyClient">Instance of <see cref="IWebhookClient{GotifyOption}"/>.</param>
|
||||
/// <param name="pushbulletClient">Instance of the <see cref="IWebhookClient{PushbulletOption}"/>.</param>
|
||||
/// <param name="pushoverClient">Instance of the <see cref="IWebhookClient{PushoverOption}"/>.</param>
|
||||
/// <param name="slackClient">Instance of the <see cref="IWebhookClient{SlackOption}"/>.</param>
|
||||
/// <param name="smtpClient">Instance of the <see cref="IWebhookClient{SmtpOption}"/>.</param>
|
||||
/// <param name="mqttClient">Instance of the <see cref="IWebhookClient{mqttClient}"/>.</param>
|
||||
public WebhookSender(
|
||||
ILogger<WebhookSender> logger,
|
||||
IWebhookClient<DiscordOption> discordClient,
|
||||
IWebhookClient<GenericOption> genericClient,
|
||||
IWebhookClient<GenericFormOption> genericFormClient,
|
||||
IWebhookClient<GotifyOption> gotifyClient,
|
||||
IWebhookClient<PushbulletOption> pushbulletClient,
|
||||
IWebhookClient<PushoverOption> pushoverClient,
|
||||
IWebhookClient<SlackOption> slackClient,
|
||||
IWebhookClient<SmtpOption> smtpClient,
|
||||
IWebhookClient<MqttOption> mqttClient)
|
||||
{
|
||||
private readonly ILogger<WebhookSender> _logger;
|
||||
private readonly IWebhookClient<DiscordOption> _discordClient;
|
||||
private readonly IWebhookClient<GenericOption> _genericClient;
|
||||
private readonly IWebhookClient<GenericFormOption> _genericFormClient;
|
||||
private readonly IWebhookClient<GotifyOption> _gotifyClient;
|
||||
private readonly IWebhookClient<PushbulletOption> _pushbulletClient;
|
||||
private readonly IWebhookClient<PushoverOption> _pushoverClient;
|
||||
private readonly IWebhookClient<SlackOption> _slackClient;
|
||||
private readonly IWebhookClient<SmtpOption> _smtpClient;
|
||||
private readonly IWebhookClient<MqttOption> _mqttClient;
|
||||
_logger = logger;
|
||||
_discordClient = discordClient;
|
||||
_genericClient = genericClient;
|
||||
_genericFormClient = genericFormClient;
|
||||
_gotifyClient = gotifyClient;
|
||||
_pushbulletClient = pushbulletClient;
|
||||
_pushoverClient = pushoverClient;
|
||||
_slackClient = slackClient;
|
||||
_smtpClient = smtpClient;
|
||||
_mqttClient = mqttClient;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WebhookSender"/> class.
|
||||
/// </summary>
|
||||
/// <param name="logger">Instance of the <see cref="ILogger{WebhookSender}"/> interface.</param>
|
||||
/// <param name="discordClient">Instance of <see cref="IWebhookClient{DiscordOption}"/>.</param>
|
||||
/// /// <param name="genericClient">Instance of the <see cref="IWebhookClient{GenericOption}"/>.</param>
|
||||
/// <param name="genericFormClient">Instance of the <see cref="IWebhookClient{GenericFormOption}"/>.</param>
|
||||
/// <param name="gotifyClient">Instance of <see cref="IWebhookClient{GotifyOption}"/>.</param>
|
||||
/// <param name="pushbulletClient">Instance of the <see cref="IWebhookClient{PushbulletOption}"/>.</param>
|
||||
/// <param name="pushoverClient">Instance of the <see cref="IWebhookClient{PushoverOption}"/>.</param>
|
||||
/// <param name="slackClient">Instance of the <see cref="IWebhookClient{SlackOption}"/>.</param>
|
||||
/// <param name="smtpClient">Instance of the <see cref="IWebhookClient{SmtpOption}"/>.</param>
|
||||
/// <param name="mqttClient">Instance of the <see cref="IWebhookClient{mqttClient}"/>.</param>
|
||||
public WebhookSender(
|
||||
ILogger<WebhookSender> logger,
|
||||
IWebhookClient<DiscordOption> discordClient,
|
||||
IWebhookClient<GenericOption> genericClient,
|
||||
IWebhookClient<GenericFormOption> genericFormClient,
|
||||
IWebhookClient<GotifyOption> gotifyClient,
|
||||
IWebhookClient<PushbulletOption> pushbulletClient,
|
||||
IWebhookClient<PushoverOption> pushoverClient,
|
||||
IWebhookClient<SlackOption> slackClient,
|
||||
IWebhookClient<SmtpOption> smtpClient,
|
||||
IWebhookClient<MqttOption> mqttClient)
|
||||
private static PluginConfiguration Configuration =>
|
||||
WebhookPlugin.Instance!.Configuration;
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task SendNotification(NotificationType notificationType, Dictionary<string, object> itemData, Type? itemType = null)
|
||||
{
|
||||
foreach (var option in Configuration.DiscordOptions.Where(o => o.NotificationTypes.Contains(notificationType)))
|
||||
{
|
||||
_logger = logger;
|
||||
_discordClient = discordClient;
|
||||
_genericClient = genericClient;
|
||||
_genericFormClient = genericFormClient;
|
||||
_gotifyClient = gotifyClient;
|
||||
_pushbulletClient = pushbulletClient;
|
||||
_pushoverClient = pushoverClient;
|
||||
_slackClient = slackClient;
|
||||
_smtpClient = smtpClient;
|
||||
_mqttClient = mqttClient;
|
||||
await SendNotification(_discordClient, option, itemData, itemType)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static PluginConfiguration Configuration =>
|
||||
WebhookPlugin.Instance!.Configuration;
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task SendNotification(NotificationType notificationType, Dictionary<string, object> itemData, Type? itemType = null)
|
||||
foreach (var option in Configuration.GenericOptions.Where(o => o.NotificationTypes.Contains(notificationType)))
|
||||
{
|
||||
foreach (var option in Configuration.DiscordOptions.Where(o => o.NotificationTypes.Contains(notificationType)))
|
||||
{
|
||||
await SendNotification(_discordClient, option, itemData, itemType)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
foreach (var option in Configuration.GenericOptions.Where(o => o.NotificationTypes.Contains(notificationType)))
|
||||
{
|
||||
await SendNotification(_genericClient, option, itemData, itemType)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
foreach (var option in Configuration.GenericFormOptions.Where(o => o.NotificationTypes.Contains(notificationType)))
|
||||
{
|
||||
await SendNotification(_genericFormClient, option, itemData, itemType)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
foreach (var option in Configuration.GotifyOptions.Where(o => o.NotificationTypes.Contains(notificationType)))
|
||||
{
|
||||
await SendNotification(_gotifyClient, option, itemData, itemType)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
foreach (var option in Configuration.PushbulletOptions.Where(o => o.NotificationTypes.Contains(notificationType)))
|
||||
{
|
||||
await SendNotification(_pushbulletClient, option, itemData, itemType)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
foreach (var option in Configuration.PushoverOptions.Where(o => o.NotificationTypes.Contains(notificationType)))
|
||||
{
|
||||
await SendNotification(_pushoverClient, option, itemData, itemType)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
foreach (var option in Configuration.SlackOptions.Where(o => o.NotificationTypes.Contains(notificationType)))
|
||||
{
|
||||
await SendNotification(_slackClient, option, itemData, itemType)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
foreach (var option in Configuration.SmtpOptions.Where(o => o.NotificationTypes.Contains(notificationType)))
|
||||
{
|
||||
await SendNotification(_smtpClient, option, itemData, itemType)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
foreach (var option in Configuration.MqttOptions.Where(o => o.NotificationTypes.Contains(notificationType)))
|
||||
{
|
||||
await SendNotification(_mqttClient, option, itemData, itemType)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
await SendNotification(_genericClient, option, itemData, itemType)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static bool NotifyOnItem<T>(T baseOptions, Type? itemType)
|
||||
where T : BaseOption
|
||||
foreach (var option in Configuration.GenericFormOptions.Where(o => o.NotificationTypes.Contains(notificationType)))
|
||||
{
|
||||
if (itemType is null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (baseOptions.EnableAlbums && itemType == typeof(MusicAlbum))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (baseOptions.EnableMovies && itemType == typeof(Movie))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (baseOptions.EnableEpisodes && itemType == typeof(Episode))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (baseOptions.EnableSeries && itemType == typeof(Series))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (baseOptions.EnableSeasons && itemType == typeof(Season))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (baseOptions.EnableSongs && itemType == typeof(Audio))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
await SendNotification(_genericFormClient, option, itemData, itemType)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task SendNotification<T>(IWebhookClient<T> webhookClient, T option, Dictionary<string, object> itemData, Type? itemType)
|
||||
where T : BaseOption
|
||||
foreach (var option in Configuration.GotifyOptions.Where(o => o.NotificationTypes.Contains(notificationType)))
|
||||
{
|
||||
if (NotifyOnItem(option, itemType))
|
||||
await SendNotification(_gotifyClient, option, itemData, itemType)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
foreach (var option in Configuration.PushbulletOptions.Where(o => o.NotificationTypes.Contains(notificationType)))
|
||||
{
|
||||
await SendNotification(_pushbulletClient, option, itemData, itemType)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
foreach (var option in Configuration.PushoverOptions.Where(o => o.NotificationTypes.Contains(notificationType)))
|
||||
{
|
||||
await SendNotification(_pushoverClient, option, itemData, itemType)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
foreach (var option in Configuration.SlackOptions.Where(o => o.NotificationTypes.Contains(notificationType)))
|
||||
{
|
||||
await SendNotification(_slackClient, option, itemData, itemType)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
foreach (var option in Configuration.SmtpOptions.Where(o => o.NotificationTypes.Contains(notificationType)))
|
||||
{
|
||||
await SendNotification(_smtpClient, option, itemData, itemType)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
foreach (var option in Configuration.MqttOptions.Where(o => o.NotificationTypes.Contains(notificationType)))
|
||||
{
|
||||
await SendNotification(_mqttClient, option, itemData, itemType)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool NotifyOnItem<T>(T baseOptions, Type? itemType)
|
||||
where T : BaseOption
|
||||
{
|
||||
if (itemType is null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (baseOptions.EnableAlbums && itemType == typeof(MusicAlbum))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (baseOptions.EnableMovies && itemType == typeof(Movie))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (baseOptions.EnableEpisodes && itemType == typeof(Episode))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (baseOptions.EnableSeries && itemType == typeof(Series))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (baseOptions.EnableSeasons && itemType == typeof(Season))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (baseOptions.EnableSongs && itemType == typeof(Audio))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private async Task SendNotification<T>(IWebhookClient<T> webhookClient, T option, Dictionary<string, object> itemData, Type? itemType)
|
||||
where T : BaseOption
|
||||
{
|
||||
if (NotifyOnItem(option, itemType))
|
||||
{
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
await webhookClient.SendAsync(option, itemData)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(e, "Unable to send notification");
|
||||
}
|
||||
await webhookClient.SendAsync(option, itemData)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(e, "Unable to send notification");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -58,4 +58,4 @@ public class WebhookServerEntryPoint : IServerEntryPoint
|
||||
{
|
||||
await _mqttClients.UpdateClients(Configuration.MqttOptions).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user