fix:: Plugin Erste Tests
All checks were successful
Create Release PR / Create Release PR (push) Successful in 17s

This commit is contained in:
2026-03-01 16:01:26 +01:00
commit b3304e61bf
18 changed files with 2060 additions and 0 deletions

View File

@@ -0,0 +1,69 @@
using MediaBrowser.Model.Plugins;
namespace Jellyfin.Plugin.SmartNotify.Configuration;
/// <summary>
/// Plugin configuration.
/// </summary>
public class PluginConfiguration : BasePluginConfiguration
{
/// <summary>
/// Initializes a new instance of the <see cref="PluginConfiguration"/> class.
/// </summary>
public PluginConfiguration()
{
DiscordWebhookUrl = string.Empty;
NotificationDelayMinutes = 5;
GroupingWindowMinutes = 30;
EnableMovieNotifications = true;
EnableEpisodeNotifications = true;
SuppressUpgrades = true;
BotUsername = "Jellyfin SmartNotify";
EmbedColor = 3447003; // Discord blue
}
/// <summary>
/// Gets or sets the Discord webhook URL.
/// </summary>
public string DiscordWebhookUrl { get; set; }
/// <summary>
/// Gets or sets the delay before processing notifications (allows metadata to settle).
/// </summary>
public int NotificationDelayMinutes { get; set; }
/// <summary>
/// Gets or sets the time window in which episodes are grouped together.
/// </summary>
public int GroupingWindowMinutes { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to notify for movies.
/// </summary>
public bool EnableMovieNotifications { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to notify for episodes.
/// </summary>
public bool EnableEpisodeNotifications { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to suppress notifications for quality upgrades.
/// </summary>
public bool SuppressUpgrades { get; set; }
/// <summary>
/// Gets or sets the Discord bot username.
/// </summary>
public string BotUsername { get; set; }
/// <summary>
/// Gets or sets the Discord embed color.
/// </summary>
public int EmbedColor { get; set; }
/// <summary>
/// Gets or sets the Jellyfin server URL for image links.
/// </summary>
public string ServerUrl { get; set; } = string.Empty;
}

View File

@@ -0,0 +1,163 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>SmartNotify</title>
</head>
<body>
<div id="SmartNotifyConfigPage" data-role="page" class="page type-interior pluginConfigurationPage" data-require="emby-input,emby-button,emby-checkbox,emby-select">
<div data-role="content">
<div class="content-primary">
<form id="SmartNotifyConfigForm">
<div class="sectionTitleContainer flex align-items-center">
<h2 class="sectionTitle">SmartNotify Konfiguration</h2>
</div>
<div class="verticalSection">
<p class="fieldDescription">
SmartNotify erkennt automatisch, ob ein Item wirklich <strong>neu</strong> ist oder nur ein
<strong>Qualitäts-Upgrade</strong> einer bereits existierenden Datei. Benachrichtigungen
werden intelligent gruppiert (z.B. "Episode 1-12 hinzugefügt").
</p>
</div>
<div class="verticalSection">
<h3 class="sectionTitle">Discord Einstellungen</h3>
<div class="inputContainer">
<label class="inputLabel inputLabelUnfocused" for="txtDiscordWebhookUrl">Discord Webhook URL</label>
<input is="emby-input" type="url" id="txtDiscordWebhookUrl" required />
<div class="fieldDescription">Die Webhook-URL deines Discord-Kanals</div>
</div>
<div class="inputContainer">
<label class="inputLabel inputLabelUnfocused" for="txtBotUsername">Bot Name</label>
<input is="emby-input" type="text" id="txtBotUsername" />
<div class="fieldDescription">Name des Bots in Discord</div>
</div>
<div class="inputContainer">
<label class="inputLabel inputLabelUnfocused" for="txtEmbedColor">Embed Farbe (Dezimal)</label>
<input is="emby-input" type="number" id="txtEmbedColor" />
<div class="fieldDescription">Discord Embed-Farbe als Dezimalzahl (z.B. 3447003 für Blau)</div>
</div>
</div>
<div class="verticalSection">
<h3 class="sectionTitle">Server Einstellungen</h3>
<div class="inputContainer">
<label class="inputLabel inputLabelUnfocused" for="txtServerUrl">Server URL</label>
<input is="emby-input" type="url" id="txtServerUrl" placeholder="https://jellyfin.example.com" />
<div class="fieldDescription">Öffentliche URL deines Jellyfin-Servers (für Bilder in Discord)</div>
</div>
</div>
<div class="verticalSection">
<h3 class="sectionTitle">Benachrichtigungstypen</h3>
<div class="checkboxContainer checkboxContainer-withDescription">
<label>
<input is="emby-checkbox" type="checkbox" id="chkEnableEpisodeNotifications" />
<span>Episoden-Benachrichtigungen</span>
</label>
<div class="fieldDescription checkboxFieldDescription">Benachrichtigungen für neue Episoden senden</div>
</div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label>
<input is="emby-checkbox" type="checkbox" id="chkEnableMovieNotifications" />
<span>Film-Benachrichtigungen</span>
</label>
<div class="fieldDescription checkboxFieldDescription">Benachrichtigungen für neue Filme senden</div>
</div>
<div class="checkboxContainer checkboxContainer-withDescription">
<label>
<input is="emby-checkbox" type="checkbox" id="chkSuppressUpgrades" />
<span>Qualitäts-Upgrades unterdrücken</span>
</label>
<div class="fieldDescription checkboxFieldDescription">
Keine Benachrichtigungen senden, wenn eine Datei durch eine bessere Qualität ersetzt wird
</div>
</div>
</div>
<div class="verticalSection">
<h3 class="sectionTitle">Timing</h3>
<div class="inputContainer">
<label class="inputLabel inputLabelUnfocused" for="txtNotificationDelayMinutes">Verzögerung (Minuten)</label>
<input is="emby-input" type="number" id="txtNotificationDelayMinutes" min="1" max="60" />
<div class="fieldDescription">
Wartezeit bevor eine Benachrichtigung gesendet wird.
Erlaubt Metadaten-Aktualisierung und Erkennung von Ersetzungen.
</div>
</div>
<div class="inputContainer">
<label class="inputLabel inputLabelUnfocused" for="txtGroupingWindowMinutes">Gruppierungsfenster (Minuten)</label>
<input is="emby-input" type="number" id="txtGroupingWindowMinutes" min="5" max="120" />
<div class="fieldDescription">
Zeitfenster in dem Episoden derselben Serie zusammengefasst werden.
Z.B. bei 30 Minuten: Wenn Episode 1-12 innerhalb von 30 Minuten hinzugefügt werden,
wird nur eine Benachrichtigung gesendet.
</div>
</div>
</div>
<div>
<button is="emby-button" type="submit" class="raised button-submit block">
<span>Speichern</span>
</button>
</div>
</form>
</div>
</div>
<script type="text/javascript">
var SmartNotifyConfig = {
pluginUniqueId: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'
};
document.querySelector('#SmartNotifyConfigPage')
.addEventListener('pageshow', function () {
Dashboard.showLoadingMsg();
ApiClient.getPluginConfiguration(SmartNotifyConfig.pluginUniqueId).then(function (config) {
document.querySelector('#txtDiscordWebhookUrl').value = config.DiscordWebhookUrl || '';
document.querySelector('#txtBotUsername').value = config.BotUsername || 'Jellyfin SmartNotify';
document.querySelector('#txtEmbedColor').value = config.EmbedColor || 3447003;
document.querySelector('#txtServerUrl').value = config.ServerUrl || '';
document.querySelector('#chkEnableEpisodeNotifications').checked = config.EnableEpisodeNotifications;
document.querySelector('#chkEnableMovieNotifications').checked = config.EnableMovieNotifications;
document.querySelector('#chkSuppressUpgrades').checked = config.SuppressUpgrades;
document.querySelector('#txtNotificationDelayMinutes').value = config.NotificationDelayMinutes || 5;
document.querySelector('#txtGroupingWindowMinutes').value = config.GroupingWindowMinutes || 30;
Dashboard.hideLoadingMsg();
});
});
document.querySelector('#SmartNotifyConfigForm')
.addEventListener('submit', function (e) {
e.preventDefault();
Dashboard.showLoadingMsg();
ApiClient.getPluginConfiguration(SmartNotifyConfig.pluginUniqueId).then(function (config) {
config.DiscordWebhookUrl = document.querySelector('#txtDiscordWebhookUrl').value;
config.BotUsername = document.querySelector('#txtBotUsername').value;
config.EmbedColor = parseInt(document.querySelector('#txtEmbedColor').value) || 3447003;
config.ServerUrl = document.querySelector('#txtServerUrl').value;
config.EnableEpisodeNotifications = document.querySelector('#chkEnableEpisodeNotifications').checked;
config.EnableMovieNotifications = document.querySelector('#chkEnableMovieNotifications').checked;
config.SuppressUpgrades = document.querySelector('#chkSuppressUpgrades').checked;
config.NotificationDelayMinutes = parseInt(document.querySelector('#txtNotificationDelayMinutes').value) || 5;
config.GroupingWindowMinutes = parseInt(document.querySelector('#txtGroupingWindowMinutes').value) || 30;
ApiClient.updatePluginConfiguration(SmartNotifyConfig.pluginUniqueId, config).then(function () {
Dashboard.processPluginConfigurationUpdateResult();
});
});
return false;
});
</script>
</div>
</body>
</html>