mirror of
https://github.com/jellyfin/jellyfin-plugin-webhook.git
synced 2024-11-23 05:59:58 +00:00
Merge pull request #15 from crobibero/send-all-props
This commit is contained in:
commit
428209036d
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Net.Http;
|
||||
using System.Net.Mime;
|
||||
@ -31,6 +32,11 @@ namespace Jellyfin.Plugin.Webhook.Destinations.Discord
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(options.WebhookUri))
|
||||
{
|
||||
throw new ArgumentException(nameof(options.WebhookUri));
|
||||
}
|
||||
|
||||
// Add discord specific properties.
|
||||
data["MentionType"] = GetMentionType(options.MentionType);
|
||||
if (!string.IsNullOrEmpty(options.EmbedColor))
|
||||
@ -53,10 +59,12 @@ namespace Jellyfin.Plugin.Webhook.Destinations.Discord
|
||||
using var content = new StringContent(body, Encoding.UTF8, MediaTypeNames.Application.Json);
|
||||
using var response = await _httpClientFactory
|
||||
.CreateClient(NamedClient.Default)
|
||||
.PostAsync(options.WebhookUri, content);
|
||||
.PostAsync(new Uri(options.WebhookUri), content)
|
||||
.ConfigureAwait(false);
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
var responseStr = await response.Content.ReadAsStringAsync();
|
||||
var responseStr = await response.Content.ReadAsStringAsync()
|
||||
.ConfigureAwait(false);
|
||||
_logger.LogWarning("Error sending notification: {Response}", responseStr);
|
||||
}
|
||||
}
|
||||
|
@ -70,10 +70,12 @@ namespace Jellyfin.Plugin.Webhook.Destinations.Generic
|
||||
httpRequestMessage.Content = new StringContent(body, Encoding.UTF8, contentType);
|
||||
using var response = await _httpClientFactory
|
||||
.CreateClient(NamedClient.Default)
|
||||
.SendAsync(httpRequestMessage);
|
||||
.SendAsync(httpRequestMessage)
|
||||
.ConfigureAwait(false);
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
var responseStr = await response.Content.ReadAsStringAsync();
|
||||
var responseStr = await response.Content.ReadAsStringAsync()
|
||||
.ConfigureAwait(false);
|
||||
_logger.LogWarning("Error sending notification: {Response}", responseStr);
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ namespace Jellyfin.Plugin.Webhook.Destinations.Gotify
|
||||
{
|
||||
if (string.IsNullOrEmpty(options.WebhookUri))
|
||||
{
|
||||
throw new NullReferenceException(nameof(options.WebhookUri));
|
||||
throw new ArgumentException(nameof(options.WebhookUri));
|
||||
}
|
||||
|
||||
// Add gotify specific properties.
|
||||
@ -44,10 +44,12 @@ namespace Jellyfin.Plugin.Webhook.Destinations.Gotify
|
||||
using var content = new StringContent(body, Encoding.UTF8, MediaTypeNames.Application.Json);
|
||||
using var response = await _httpClientFactory
|
||||
.CreateClient(NamedClient.Default)
|
||||
.PostAsync(options.WebhookUri.TrimEnd() + $"/message?token={options.Token}", content);
|
||||
.PostAsync(new Uri(options.WebhookUri.TrimEnd() + $"/message?token={options.Token}"), content)
|
||||
.ConfigureAwait(false);
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
var responseStr = await response.Content.ReadAsStringAsync();
|
||||
var responseStr = await response.Content.ReadAsStringAsync()
|
||||
.ConfigureAwait(false);
|
||||
_logger.LogWarning("Error sending notification: {Response}", responseStr);
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,11 @@
|
||||
/// </summary>
|
||||
public enum NotificationType
|
||||
{
|
||||
/// <summary>
|
||||
/// No notification type.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Item added notification.
|
||||
/// </summary>
|
||||
|
@ -45,10 +45,12 @@ namespace Jellyfin.Plugin.Webhook.Destinations.Pushbullet
|
||||
|
||||
using var response = await _httpClientFactory
|
||||
.CreateClient(NamedClient.Default)
|
||||
.SendAsync(requestOptions);
|
||||
.SendAsync(requestOptions)
|
||||
.ConfigureAwait(false);
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
var responseStr = await response.Content.ReadAsStringAsync();
|
||||
var responseStr = await response.Content.ReadAsStringAsync()
|
||||
.ConfigureAwait(false);
|
||||
_logger.LogWarning("Error sending notification: {Response}", responseStr);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Net.Mime;
|
||||
using System.Text;
|
||||
@ -52,7 +53,7 @@ namespace Jellyfin.Plugin.Webhook.Destinations.Pushover
|
||||
data["MessageUrlTitle"] = options.MessageUrlTitle;
|
||||
}
|
||||
|
||||
if (options.MessagePriority.HasValue)
|
||||
if (options.MessagePriority is not null)
|
||||
{
|
||||
data["MessagePriority"] = options.MessagePriority;
|
||||
}
|
||||
@ -67,10 +68,12 @@ namespace Jellyfin.Plugin.Webhook.Destinations.Pushover
|
||||
using var content = new StringContent(body, Encoding.UTF8, MediaTypeNames.Application.Json);
|
||||
using var response = await _httpClientFactory
|
||||
.CreateClient(NamedClient.Default)
|
||||
.PostAsync(string.IsNullOrEmpty(options.WebhookUri) ? PushoverOption.ApiUrl : options.WebhookUri, content);
|
||||
.PostAsync(string.IsNullOrEmpty(options.WebhookUri) ? PushoverOption.ApiUrl : new Uri(options.WebhookUri), content)
|
||||
.ConfigureAwait(false);
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
var responseStr = await response.Content.ReadAsStringAsync();
|
||||
var responseStr = await response.Content.ReadAsStringAsync()
|
||||
.ConfigureAwait(false);
|
||||
_logger.LogWarning("Error sending notification: {Response}", responseStr);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using System;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Destinations.Pushover
|
||||
{
|
||||
@ -11,7 +12,7 @@ namespace Jellyfin.Plugin.Webhook.Destinations.Pushover
|
||||
/// The webhook endpoint.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public const string ApiUrl = "https://api.pushover.net/1/messages.json";
|
||||
public static readonly Uri ApiUrl = new Uri("https://api.pushover.net/1/messages.json");
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pushover token.
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Net.Mime;
|
||||
using System.Text;
|
||||
@ -30,6 +31,11 @@ namespace Jellyfin.Plugin.Webhook.Destinations.Slack
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(options.WebhookUri))
|
||||
{
|
||||
throw new ArgumentException(nameof(options.WebhookUri));
|
||||
}
|
||||
|
||||
data["SlackUsername"] = options.Username;
|
||||
data["SlackIconUrl"] = options.IconUrl;
|
||||
|
||||
@ -38,10 +44,12 @@ namespace Jellyfin.Plugin.Webhook.Destinations.Slack
|
||||
using var content = new StringContent(body, Encoding.UTF8, MediaTypeNames.Application.Json);
|
||||
using var response = await _httpClientFactory
|
||||
.CreateClient(NamedClient.Default)
|
||||
.PostAsync(options.WebhookUri, content);
|
||||
.PostAsync(new Uri(options.WebhookUri), content)
|
||||
.ConfigureAwait(false);
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
var responseStr = await response.Content.ReadAsStringAsync();
|
||||
var responseStr = await response.Content.ReadAsStringAsync()
|
||||
.ConfigureAwait(false);
|
||||
_logger.LogWarning("Error sending notification: {Response}", responseStr);
|
||||
}
|
||||
}
|
||||
|
@ -29,20 +29,23 @@ namespace Jellyfin.Plugin.Webhook.Destinations.Smtp
|
||||
message.From.Add(new MailboxAddress(options.SenderAddress, options.SenderAddress));
|
||||
message.To.Add(new MailboxAddress(options.ReceiverAddress, options.ReceiverAddress));
|
||||
|
||||
message.Subject = options.GetSubjectTemplate()(data);
|
||||
message.Subject = options.GetCompiledSubjectTemplate()(data);
|
||||
message.Body = new TextPart(options.IsHtml ? "html" : "plain")
|
||||
{
|
||||
Text = options.GetMessageBody(data)
|
||||
};
|
||||
|
||||
using var smtpClient = new MailKit.Net.Smtp.SmtpClient();
|
||||
await smtpClient.ConnectAsync(options.SmtpServer, options.SmtpPort, options.UseSsl);
|
||||
await smtpClient.ConnectAsync(options.SmtpServer, options.SmtpPort, options.UseSsl)
|
||||
.ConfigureAwait(false);
|
||||
if (options.UseCredentials)
|
||||
{
|
||||
await smtpClient.AuthenticateAsync(options.Username, options.Password);
|
||||
await smtpClient.AuthenticateAsync(options.Username, options.Password)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await smtpClient.SendAsync(message);
|
||||
await smtpClient.SendAsync(message)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -64,7 +64,7 @@ namespace Jellyfin.Plugin.Webhook.Destinations.Smtp
|
||||
/// Gets the compiled handlebars subject template.
|
||||
/// </summary>
|
||||
/// <returns>The compiled handlebars subject template.</returns>
|
||||
public HandlebarsTemplate<object, string> GetSubjectTemplate()
|
||||
public HandlebarsTemplate<object, string> GetCompiledSubjectTemplate()
|
||||
{
|
||||
return _compiledSubjectTemplate ??= Handlebars.Compile(HandlebarsFunctionHelpers.Base64Decode(SubjectTemplate));
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ using Jellyfin.Data.Entities;
|
||||
using Jellyfin.Plugin.Webhook.Destinations;
|
||||
using MediaBrowser.Common;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Session;
|
||||
@ -44,7 +45,7 @@ namespace Jellyfin.Plugin.Webhook.Helpers
|
||||
/// <returns>The data object.</returns>
|
||||
public static Dictionary<string, object> AddBaseItemData(this Dictionary<string, object> dataObject, BaseItem? item)
|
||||
{
|
||||
if (item == null)
|
||||
if (item is null)
|
||||
{
|
||||
return dataObject;
|
||||
}
|
||||
@ -56,56 +57,96 @@ namespace Jellyfin.Plugin.Webhook.Helpers
|
||||
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.HasValue)
|
||||
if (item.ProductionYear is not null)
|
||||
{
|
||||
dataObject["Year"] = item.ProductionYear;
|
||||
}
|
||||
|
||||
switch (item)
|
||||
{
|
||||
case Season:
|
||||
if (!string.IsNullOrEmpty(item.Parent?.Name))
|
||||
case Season season:
|
||||
if (!string.IsNullOrEmpty(season.Series?.Name))
|
||||
{
|
||||
dataObject["SeriesName"] = item.Parent.Name.Escape();
|
||||
dataObject["SeriesName"] = season.Series.Name.Escape();
|
||||
}
|
||||
|
||||
if (item.Parent?.ProductionYear != null)
|
||||
if (season.Series?.ProductionYear is not null)
|
||||
{
|
||||
dataObject["Year"] = item.Parent.ProductionYear;
|
||||
dataObject["Year"] = season.Series.ProductionYear;
|
||||
}
|
||||
|
||||
if (item.IndexNumber.HasValue)
|
||||
if (season.IndexNumber is not null)
|
||||
{
|
||||
dataObject["SeasonNumber"] = item.IndexNumber;
|
||||
dataObject["SeasonNumber00"] = item.IndexNumber.Value.ToString("00", CultureInfo.InvariantCulture);
|
||||
dataObject["SeasonNumber000"] = item.IndexNumber.Value.ToString("000", CultureInfo.InvariantCulture);
|
||||
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:
|
||||
if (!string.IsNullOrEmpty(item.Parent?.Parent?.Name))
|
||||
case Episode episode:
|
||||
if (!string.IsNullOrEmpty(episode.Series?.Name))
|
||||
{
|
||||
dataObject["SeriesName"] = item.Parent.Parent.Name.Escape();
|
||||
dataObject["SeriesName"] = episode.Series.Name.Escape();
|
||||
}
|
||||
|
||||
if (item.Parent?.IndexNumber != null)
|
||||
if (episode.Season?.IndexNumber is not null)
|
||||
{
|
||||
dataObject["SeasonNumber"] = item.Parent.IndexNumber;
|
||||
dataObject["SeasonNumber00"] = item.Parent.IndexNumber.Value.ToString("00", CultureInfo.InvariantCulture);
|
||||
dataObject["SeasonNumber000"] = item.Parent.IndexNumber.Value.ToString("000", CultureInfo.InvariantCulture);
|
||||
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 (item.IndexNumber.HasValue)
|
||||
if (episode.IndexNumber is not null)
|
||||
{
|
||||
dataObject["EpisodeNumber"] = item.IndexNumber;
|
||||
dataObject["EpisodeNumber00"] = item.IndexNumber.Value.ToString("00", CultureInfo.InvariantCulture);
|
||||
dataObject["EpisodeNumber000"] = item.IndexNumber.Value.ToString("000", CultureInfo.InvariantCulture);
|
||||
dataObject["EpisodeNumber"] = episode.IndexNumber;
|
||||
dataObject["EpisodeNumber00"] = episode.IndexNumber.Value.ToString("00", CultureInfo.InvariantCulture);
|
||||
dataObject["EpisodeNumber000"] = episode.IndexNumber.Value.ToString("000", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
if (item.Parent?.Parent?.ProductionYear != null)
|
||||
if (episode.IndexNumberEnd is not null)
|
||||
{
|
||||
dataObject["Year"] = item.Parent.Parent.ProductionYear;
|
||||
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;
|
||||
@ -128,7 +169,7 @@ namespace Jellyfin.Plugin.Webhook.Helpers
|
||||
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");
|
||||
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;
|
||||
@ -229,6 +270,6 @@ namespace Jellyfin.Plugin.Webhook.Helpers
|
||||
/// <param name="input">Input string.</param>
|
||||
/// <returns>Escaped string.</returns>
|
||||
private static string Escape(this string? input)
|
||||
=> input?.Replace("\"", "\\\"") ?? string.Empty;
|
||||
=> input?.Replace("\"", "\\\"", StringComparison.Ordinal) ?? string.Empty;
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Jellyfin.Plugin.Webhook.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Periodic async helper.
|
||||
/// </summary>
|
||||
public static class PeriodicAsyncHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Runs an async function periodically.
|
||||
/// </summary>
|
||||
/// <param name="taskFactory">The task factory.</param>
|
||||
/// <param name="interval">The run interval.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
public static async Task PeriodicAsync(
|
||||
Func<Task> taskFactory,
|
||||
TimeSpan interval,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
var delayTask = Task.Delay(interval, cancellationToken);
|
||||
await taskFactory();
|
||||
await delayTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -7,11 +7,14 @@
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Nullable>enable</Nullable>
|
||||
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
|
||||
<CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet>
|
||||
<NoWarn>CA1819</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Handlebars.Net" Version="2.0.4" />
|
||||
<PackageReference Include="Jellyfin.Controller" Version="10.7.0-rc4" />
|
||||
<PackageReference Include="Jellyfin.Controller" Version="10.7-*" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -32,7 +32,7 @@ namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(GenericEventArgs<AuthenticationRequest> eventArgs)
|
||||
{
|
||||
if (eventArgs.Argument == null)
|
||||
if (eventArgs.Argument is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -46,7 +46,8 @@ namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
dataObject[nameof(eventArgs.Argument.DeviceId)] = eventArgs.Argument.DeviceId;
|
||||
dataObject[nameof(eventArgs.Argument.DeviceName)] = eventArgs.Argument.DeviceName;
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.AuthenticationFailure, dataObject);
|
||||
await _webhookSender.SendNotification(NotificationType.AuthenticationFailure, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
@ -32,7 +32,7 @@ namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(GenericEventArgs<AuthenticationResult> eventArgs)
|
||||
{
|
||||
if (eventArgs.Argument == null)
|
||||
if (eventArgs.Argument is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -41,7 +41,8 @@ namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.AuthenticationSuccess)
|
||||
.AddUserData(eventArgs.Argument.User);
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.AuthenticationSuccess, dataObject);
|
||||
await _webhookSender.SendNotification(NotificationType.AuthenticationSuccess, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
@ -43,7 +43,8 @@ namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
dataObject[nameof(request.User.Username)] = request.User.Username;
|
||||
dataObject["UserId"] = request.User.Id;
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.Generic, dataObject);
|
||||
await _webhookSender.SendNotification(NotificationType.Generic, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
@ -50,7 +50,7 @@ namespace Jellyfin.Plugin.Webhook.Notifiers.ItemAddedNotifier
|
||||
foreach (var (key, container) in currentItems)
|
||||
{
|
||||
var item = _libraryManager.GetItemById(key);
|
||||
if (item == null)
|
||||
if (item is null)
|
||||
{
|
||||
// Remove item from queue.
|
||||
_itemProcessQueue.TryRemove(key, out _);
|
||||
@ -76,7 +76,8 @@ namespace Jellyfin.Plugin.Webhook.Notifiers.ItemAddedNotifier
|
||||
.AddBaseItemData(item);
|
||||
|
||||
var itemType = item.GetType();
|
||||
await _webhookSender.SendNotification(NotificationType.ItemAdded, dataObject, itemType);
|
||||
await _webhookSender.SendNotification(NotificationType.ItemAdded, dataObject, itemType)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
// Remove item from queue.
|
||||
_itemProcessQueue.TryRemove(key, out _);
|
||||
|
@ -34,7 +34,8 @@ namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.PendingRestart);
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.PendingRestart, dataObject);
|
||||
await _webhookSender.SendNotification(NotificationType.PendingRestart, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
@ -32,7 +32,7 @@ namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(PlaybackProgressEventArgs eventArgs)
|
||||
{
|
||||
if (eventArgs.Item == null)
|
||||
if (eventArgs.Item is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -62,7 +62,8 @@ namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
["UserId"] = user.Id
|
||||
};
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.PlaybackProgress, userDataObject, eventArgs.Item.GetType());
|
||||
await _webhookSender.SendNotification(NotificationType.PlaybackProgress, userDataObject, eventArgs.Item.GetType())
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(PlaybackStartEventArgs eventArgs)
|
||||
{
|
||||
if (eventArgs.Item == null)
|
||||
if (eventArgs.Item is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -62,7 +62,8 @@ namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
["UserId"] = user.Id
|
||||
};
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.PlaybackStart, userDataObject, eventArgs.Item.GetType());
|
||||
await _webhookSender.SendNotification(NotificationType.PlaybackStart, userDataObject, eventArgs.Item.GetType())
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(PlaybackStopEventArgs eventArgs)
|
||||
{
|
||||
if (eventArgs.Item == null)
|
||||
if (eventArgs.Item is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -63,7 +63,8 @@ namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
["UserId"] = user.Id
|
||||
};
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.PlaybackStop, userDataObject, eventArgs.Item.GetType());
|
||||
await _webhookSender.SendNotification(NotificationType.PlaybackStop, userDataObject, eventArgs.Item.GetType())
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,8 @@ namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.PluginInstallationCancelled)
|
||||
.AddPluginInstallationInfo(eventArgs.Argument);
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.PluginInstallationCancelled, dataObject);
|
||||
await _webhookSender.SendNotification(NotificationType.PluginInstallationCancelled, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
@ -36,7 +36,8 @@ namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
.AddPluginInstallationInfo(eventArgs.InstallationInfo)
|
||||
.AddExceptionInfo(eventArgs.Exception);
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.PluginInstallationFailed, dataObject);
|
||||
await _webhookSender.SendNotification(NotificationType.PluginInstallationFailed, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
@ -35,7 +35,8 @@ namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.PluginInstalled)
|
||||
.AddPluginInstallationInfo(eventArgs.Argument);
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.PluginInstalled, dataObject);
|
||||
await _webhookSender.SendNotification(NotificationType.PluginInstalled, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
@ -35,7 +35,8 @@ namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.PluginInstalling)
|
||||
.AddPluginInstallationInfo(eventArgs.Argument);
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.PluginInstalling, dataObject);
|
||||
await _webhookSender.SendNotification(NotificationType.PluginInstalling, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
@ -39,7 +39,8 @@ namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
dataObject["PluginVersion"] = eventArgs.Argument.Version;
|
||||
dataObject["PluginStatus"] = eventArgs.Argument.Status;
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.PluginUninstalled, dataObject);
|
||||
await _webhookSender.SendNotification(NotificationType.PluginUninstalled, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
@ -35,7 +35,8 @@ namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.PluginUpdated)
|
||||
.AddPluginInstallationInfo(eventArgs.Argument);
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.PluginUpdated, dataObject);
|
||||
await _webhookSender.SendNotification(NotificationType.PluginUpdated, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
@ -31,7 +31,7 @@ namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(SessionStartedEventArgs eventArgs)
|
||||
{
|
||||
if (eventArgs.Argument == null)
|
||||
if (eventArgs.Argument is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -41,7 +41,8 @@ namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
.AddSessionInfoData(eventArgs.Argument)
|
||||
.AddBaseItemData(eventArgs.Argument.FullNowPlayingItem);
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.SessionStart, dataObject);
|
||||
await _webhookSender.SendNotification(NotificationType.SessionStart, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
@ -31,7 +31,7 @@ namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
/// <inheritdoc />
|
||||
public async Task OnEvent(SubtitleDownloadFailureEventArgs eventArgs)
|
||||
{
|
||||
if (eventArgs.Item == null)
|
||||
if (eventArgs.Item is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -39,7 +39,8 @@ namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
var dataObject = DataObjectHelpers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.SubtitleDownloadFailure)
|
||||
.AddBaseItemData(eventArgs.Item);
|
||||
await _webhookSender.SendNotification(NotificationType.SubtitleDownloadFailure, dataObject, eventArgs.Item.GetType());
|
||||
await _webhookSender.SendNotification(NotificationType.SubtitleDownloadFailure, dataObject, eventArgs.Item.GetType())
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
@ -47,7 +47,8 @@ namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
dataObject["ResultErrorMessage"] = eventArgs.Result.ErrorMessage;
|
||||
dataObject["ResultLongErrorMessage"] = eventArgs.Result.LongErrorMessage;
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.TaskCompleted, dataObject);
|
||||
await _webhookSender.SendNotification(NotificationType.TaskCompleted, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
@ -35,7 +35,8 @@ namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.UserCreated)
|
||||
.AddUserData(eventArgs.Argument);
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.UserCreated, dataObject);
|
||||
await _webhookSender.SendNotification(NotificationType.UserCreated, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
@ -35,7 +35,8 @@ namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.UserDeleted)
|
||||
.AddUserData(eventArgs.Argument);
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.UserDeleted, dataObject);
|
||||
await _webhookSender.SendNotification(NotificationType.UserDeleted, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
@ -35,7 +35,8 @@ namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.UserLockedOut)
|
||||
.AddUserData(eventArgs.Argument);
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.UserLockedOut, dataObject);
|
||||
await _webhookSender.SendNotification(NotificationType.UserLockedOut, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
@ -35,7 +35,8 @@ namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.UserPasswordChanged)
|
||||
.AddUserData(eventArgs.Argument);
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.UserPasswordChanged, dataObject);
|
||||
await _webhookSender.SendNotification(NotificationType.UserPasswordChanged, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
@ -35,7 +35,8 @@ namespace Jellyfin.Plugin.Webhook.Notifiers
|
||||
.GetBaseDataObject(_applicationHost, NotificationType.UserUpdated)
|
||||
.AddUserData(eventArgs.Argument);
|
||||
|
||||
await _webhookSender.SendNotification(NotificationType.UserUpdated, dataObject);
|
||||
await _webhookSender.SendNotification(NotificationType.UserUpdated, dataObject)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Jellyfin.Plugin.Webhook.Configuration;
|
||||
using Jellyfin.Plugin.Webhook.Destinations;
|
||||
@ -62,52 +63,58 @@ namespace Jellyfin.Plugin.Webhook
|
||||
}
|
||||
|
||||
private static PluginConfiguration Configuration =>
|
||||
WebhookPlugin.Instance?.Configuration
|
||||
?? throw new NullReferenceException(nameof(WebhookPlugin.Instance.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)))
|
||||
{
|
||||
await SendNotification(_discordClient, option, itemData, itemType);
|
||||
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);
|
||||
await SendNotification(_genericClient, option, itemData, itemType)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
foreach (var option in Configuration.GotifyOptions.Where(o => o.NotificationTypes.Contains(notificationType)))
|
||||
{
|
||||
await SendNotification(_gotifyClient, option, itemData, 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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
await SendNotification(_smtpClient, option, itemData, itemType)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool NotifyOnItem<T>(T baseOptions, Type? itemType)
|
||||
where T : BaseOption
|
||||
{
|
||||
if (itemType == null)
|
||||
if (itemType is null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -152,7 +159,8 @@ namespace Jellyfin.Plugin.Webhook
|
||||
{
|
||||
try
|
||||
{
|
||||
await webhookClient.SendAsync(option, itemData);
|
||||
await webhookClient.SendAsync(option, itemData)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RuleSet Name="Rules for Jellyfin.Server" Description="Code analysis rules for Jellyfin.Server.csproj" ToolsVersion="14.0">
|
||||
<RuleSet Name="Rules for Jellyfin" Description="Code analysis rules for Jellyfin" ToolsVersion="14.0">
|
||||
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers">
|
||||
<!-- disable warning SA1202: 'public' members must come before 'private' members -->
|
||||
<Rule Id="SA1202" Action="Info" />
|
||||
@ -10,6 +10,8 @@
|
||||
|
||||
<!-- disable warning SA1009: Closing parenthesis should be followed by a space. -->
|
||||
<Rule Id="SA1009" Action="None" />
|
||||
<!-- disable warning SA1011: Closing square bracket should be followed by a space. -->
|
||||
<Rule Id="SA1011" Action="None" />
|
||||
<!-- disable warning SA1101: Prefix local calls with 'this.' -->
|
||||
<Rule Id="SA1101" Action="None" />
|
||||
<!-- disable warning SA1108: Block statements should not contain embedded comments -->
|
||||
@ -30,11 +32,17 @@
|
||||
<Rule Id="SA1515" Action="None" />
|
||||
<!-- disable warning SA1600: Elements should be documented -->
|
||||
<Rule Id="SA1600" Action="None" />
|
||||
<!-- disable warning SA1602: Enumeration items should be documented -->
|
||||
<Rule Id="SA1602" Action="None" />
|
||||
<!-- disable warning SA1633: The file header is missing or not located at the top of the file -->
|
||||
<Rule Id="SA1633" Action="None" />
|
||||
</Rules>
|
||||
|
||||
<Rules AnalyzerId="Microsoft.CodeAnalysis.FxCopAnalyzers" RuleNamespace="Microsoft.Design">
|
||||
<Rules AnalyzerId="Microsoft.CodeAnalysis.NetAnalyzers" RuleNamespace="Microsoft.Design">
|
||||
<!-- error on CA2016: Forward the CancellationToken parameter to methods that take one
|
||||
or pass in 'CancellationToken.None' explicitly to indicate intentionally not propagating the token -->
|
||||
<Rule Id="CA2016" Action="Error" />
|
||||
|
||||
<!-- disable warning CA1031: Do not catch general exception types -->
|
||||
<Rule Id="CA1031" Action="Info" />
|
||||
<!-- disable warning CA1032: Implement standard exception constructors -->
|
||||
@ -45,6 +53,8 @@
|
||||
<Rule Id="CA1716" Action="Info" />
|
||||
<!-- disable warning CA1720: Identifiers should not contain type names -->
|
||||
<Rule Id="CA1720" Action="Info" />
|
||||
<!-- disable warning CA1805: Do not initialize unnecessarily -->
|
||||
<Rule Id="CA1805" Action="Info" />
|
||||
<!-- disable warning CA1812: internal class that is apparently never instantiated.
|
||||
If so, remove the code from the assembly.
|
||||
If this class is intended to contain only static members, make it static -->
|
||||
@ -53,7 +63,11 @@
|
||||
<Rule Id="CA1822" Action="Info" />
|
||||
<!-- disable warning CA2000: Dispose objects before losing scope -->
|
||||
<Rule Id="CA2000" Action="Info" />
|
||||
<!-- disable warning CA5394: Do not use insecure randomness -->
|
||||
<Rule Id="CA5394" Action="Info" />
|
||||
|
||||
<!-- disable warning CA1014: Mark assemblies with CLSCompliantAttribute -->
|
||||
<Rule Id="CA1014" Action="Info" />
|
||||
<!-- disable warning CA1054: Change the type of parameter url from string to System.Uri -->
|
||||
<Rule Id="CA1054" Action="None" />
|
||||
<!-- disable warning CA1055: URI return values should not be strings -->
|
||||
|
Loading…
Reference in New Issue
Block a user