fix: Bilder und dumme min TImings!
This commit is contained in:
@@ -14,7 +14,7 @@ public class PluginConfiguration : BasePluginConfiguration
|
|||||||
{
|
{
|
||||||
DiscordWebhookUrl = string.Empty;
|
DiscordWebhookUrl = string.Empty;
|
||||||
NotificationDelayMinutes = 5;
|
NotificationDelayMinutes = 5;
|
||||||
GroupingWindowMinutes = 30;
|
GroupingWindowMinutes = 5;
|
||||||
EnableMovieNotifications = true;
|
EnableMovieNotifications = true;
|
||||||
EnableEpisodeNotifications = true;
|
EnableEpisodeNotifications = true;
|
||||||
SuppressUpgrades = true;
|
SuppressUpgrades = true;
|
||||||
|
|||||||
@@ -88,7 +88,7 @@
|
|||||||
|
|
||||||
<div class="inputContainer">
|
<div class="inputContainer">
|
||||||
<label class="inputLabel inputLabelUnfocused" for="txtNotificationDelayMinutes">Verzögerung (Minuten)</label>
|
<label class="inputLabel inputLabelUnfocused" for="txtNotificationDelayMinutes">Verzögerung (Minuten)</label>
|
||||||
<input is="emby-input" type="number" id="txtNotificationDelayMinutes" min="1" max="60" />
|
<input is="emby-input" type="number" id="txtNotificationDelayMinutes" min="0" max="60" />
|
||||||
<div class="fieldDescription">
|
<div class="fieldDescription">
|
||||||
Wartezeit bevor eine Benachrichtigung gesendet wird.
|
Wartezeit bevor eine Benachrichtigung gesendet wird.
|
||||||
Erlaubt Metadaten-Aktualisierung und Erkennung von Ersetzungen.
|
Erlaubt Metadaten-Aktualisierung und Erkennung von Ersetzungen.
|
||||||
@@ -97,7 +97,7 @@
|
|||||||
|
|
||||||
<div class="inputContainer">
|
<div class="inputContainer">
|
||||||
<label class="inputLabel inputLabelUnfocused" for="txtGroupingWindowMinutes">Gruppierungsfenster (Minuten)</label>
|
<label class="inputLabel inputLabelUnfocused" for="txtGroupingWindowMinutes">Gruppierungsfenster (Minuten)</label>
|
||||||
<input is="emby-input" type="number" id="txtGroupingWindowMinutes" min="5" max="120" />
|
<input is="emby-input" type="number" id="txtGroupingWindowMinutes" min="0" max="120" />
|
||||||
<div class="fieldDescription">
|
<div class="fieldDescription">
|
||||||
Zeitfenster in dem Episoden derselben Serie zusammengefasst werden.
|
Zeitfenster in dem Episoden derselben Serie zusammengefasst werden.
|
||||||
Z.B. bei 30 Minuten: Wenn Episode 1-12 innerhalb von 30 Minuten hinzugefügt werden,
|
Z.B. bei 30 Minuten: Wenn Episode 1-12 innerhalb von 30 Minuten hinzugefügt werden,
|
||||||
@@ -131,8 +131,8 @@
|
|||||||
document.querySelector('#chkEnableEpisodeNotifications').checked = config.EnableEpisodeNotifications;
|
document.querySelector('#chkEnableEpisodeNotifications').checked = config.EnableEpisodeNotifications;
|
||||||
document.querySelector('#chkEnableMovieNotifications').checked = config.EnableMovieNotifications;
|
document.querySelector('#chkEnableMovieNotifications').checked = config.EnableMovieNotifications;
|
||||||
document.querySelector('#chkSuppressUpgrades').checked = config.SuppressUpgrades;
|
document.querySelector('#chkSuppressUpgrades').checked = config.SuppressUpgrades;
|
||||||
document.querySelector('#txtNotificationDelayMinutes').value = config.NotificationDelayMinutes || 5;
|
document.querySelector('#txtNotificationDelayMinutes').value = config.NotificationDelayMinutes ?? 0;
|
||||||
document.querySelector('#txtGroupingWindowMinutes').value = config.GroupingWindowMinutes || 30;
|
document.querySelector('#txtGroupingWindowMinutes').value = config.GroupingWindowMinutes ?? 0;
|
||||||
Dashboard.hideLoadingMsg();
|
Dashboard.hideLoadingMsg();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -149,8 +149,8 @@
|
|||||||
config.EnableEpisodeNotifications = document.querySelector('#chkEnableEpisodeNotifications').checked;
|
config.EnableEpisodeNotifications = document.querySelector('#chkEnableEpisodeNotifications').checked;
|
||||||
config.EnableMovieNotifications = document.querySelector('#chkEnableMovieNotifications').checked;
|
config.EnableMovieNotifications = document.querySelector('#chkEnableMovieNotifications').checked;
|
||||||
config.SuppressUpgrades = document.querySelector('#chkSuppressUpgrades').checked;
|
config.SuppressUpgrades = document.querySelector('#chkSuppressUpgrades').checked;
|
||||||
config.NotificationDelayMinutes = parseInt(document.querySelector('#txtNotificationDelayMinutes').value) || 5;
|
config.NotificationDelayMinutes = parseInt(document.querySelector('#txtNotificationDelayMinutes').value) || 0;
|
||||||
config.GroupingWindowMinutes = parseInt(document.querySelector('#txtGroupingWindowMinutes').value) || 30;
|
config.GroupingWindowMinutes = parseInt(document.querySelector('#txtGroupingWindowMinutes').value) || 0;
|
||||||
ApiClient.updatePluginConfiguration(SmartNotifyConfig.pluginUniqueId, config).then(function () {
|
ApiClient.updatePluginConfiguration(SmartNotifyConfig.pluginUniqueId, config).then(function () {
|
||||||
Dashboard.processPluginConfigurationUpdateResult();
|
Dashboard.processPluginConfigurationUpdateResult();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using MediaBrowser.Controller.Entities;
|
|||||||
using MediaBrowser.Controller.Entities.Movies;
|
using MediaBrowser.Controller.Entities.Movies;
|
||||||
using MediaBrowser.Controller.Entities.TV;
|
using MediaBrowser.Controller.Entities.TV;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
|
using MediaBrowser.Model.Entities;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Timer = System.Timers.Timer;
|
using Timer = System.Timers.Timer;
|
||||||
@@ -185,10 +186,11 @@ public class SmartNotifyBackgroundService : IHostedService, IDisposable
|
|||||||
Overview = item.Overview
|
Overview = item.Overview
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set image URL
|
// Set local image path for attachment-based sending
|
||||||
if (!string.IsNullOrEmpty(serverUrl))
|
var imagePath = item.GetImagePath(ImageType.Primary, 0);
|
||||||
|
if (!string.IsNullOrEmpty(imagePath))
|
||||||
{
|
{
|
||||||
notification.ImageUrl = $"{serverUrl}/Items/{item.Id}/Images/Primary";
|
notification.ImagePath = imagePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item is Episode episode)
|
if (item is Episode episode)
|
||||||
@@ -199,10 +201,15 @@ public class SmartNotifyBackgroundService : IHostedService, IDisposable
|
|||||||
notification.EpisodeNumber = episode.IndexNumber;
|
notification.EpisodeNumber = episode.IndexNumber;
|
||||||
notification.Year = episode.ProductionYear;
|
notification.Year = episode.ProductionYear;
|
||||||
|
|
||||||
// Use series image if episode doesn't have one
|
// Use series image if episode doesn't have its own
|
||||||
if (!string.IsNullOrEmpty(serverUrl) && episode.SeriesId != Guid.Empty)
|
if (episode.SeriesId != Guid.Empty)
|
||||||
{
|
{
|
||||||
notification.ImageUrl = $"{serverUrl}/Items/{episode.SeriesId}/Images/Primary";
|
var series = _libraryManager.GetItemById(episode.SeriesId);
|
||||||
|
var seriesImage = series?.GetImagePath(ImageType.Primary, 0);
|
||||||
|
if (!string.IsNullOrEmpty(seriesImage))
|
||||||
|
{
|
||||||
|
notification.ImagePath = seriesImage;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (item is Movie movie)
|
else if (item is Movie movie)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -69,14 +70,11 @@ public class DiscordNotificationService
|
|||||||
var title = $"📺 {seriesName}";
|
var title = $"📺 {seriesName}";
|
||||||
var description = $"Neue Episoden hinzugefügt:\n{episodeDescription}";
|
var description = $"Neue Episoden hinzugefügt:\n{episodeDescription}";
|
||||||
|
|
||||||
// Get image from first notification
|
|
||||||
var imageUrl = first.ImageUrl;
|
|
||||||
|
|
||||||
await SendDiscordWebhookAsync(
|
await SendDiscordWebhookAsync(
|
||||||
config,
|
config,
|
||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
imageUrl,
|
first.ImagePath,
|
||||||
BuildExternalLinks(first.ProviderIdsJson),
|
BuildExternalLinks(first.ProviderIdsJson),
|
||||||
cancellationToken);
|
cancellationToken);
|
||||||
}
|
}
|
||||||
@@ -182,7 +180,7 @@ public class DiscordNotificationService
|
|||||||
config,
|
config,
|
||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
notification.ImageUrl,
|
notification.ImagePath,
|
||||||
BuildExternalLinks(notification.ProviderIdsJson),
|
BuildExternalLinks(notification.ProviderIdsJson),
|
||||||
cancellationToken);
|
cancellationToken);
|
||||||
}
|
}
|
||||||
@@ -236,13 +234,13 @@ public class DiscordNotificationService
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sends the actual Discord webhook request.
|
/// Sends the actual Discord webhook request, with optional image attachment.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task SendDiscordWebhookAsync(
|
private async Task SendDiscordWebhookAsync(
|
||||||
PluginConfiguration config,
|
PluginConfiguration config,
|
||||||
string title,
|
string title,
|
||||||
string description,
|
string description,
|
||||||
string? imageUrl,
|
string? imagePath,
|
||||||
string externalLinks,
|
string externalLinks,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
@@ -253,9 +251,11 @@ public class DiscordNotificationService
|
|||||||
["color"] = config.EmbedColor
|
["color"] = config.EmbedColor
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(imageUrl))
|
// If we have a local image file, reference it as attachment
|
||||||
|
var hasImage = !string.IsNullOrEmpty(imagePath) && File.Exists(imagePath);
|
||||||
|
if (hasImage)
|
||||||
{
|
{
|
||||||
embed["thumbnail"] = new Dictionary<string, string> { ["url"] = imageUrl };
|
embed["thumbnail"] = new Dictionary<string, string> { ["url"] = "attachment://poster.jpg" };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(externalLinks))
|
if (!string.IsNullOrEmpty(externalLinks))
|
||||||
@@ -277,9 +277,27 @@ public class DiscordNotificationService
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
using var client = _httpClientFactory.CreateClient();
|
using var client = _httpClientFactory.CreateClient();
|
||||||
using var content = new StringContent(json, Encoding.UTF8, "application/json");
|
HttpResponseMessage response;
|
||||||
|
|
||||||
var response = await client.PostAsync(config.DiscordWebhookUrl, content, cancellationToken);
|
if (hasImage)
|
||||||
|
{
|
||||||
|
// Send as multipart/form-data with image attachment
|
||||||
|
using var form = new MultipartFormDataContent();
|
||||||
|
form.Add(new StringContent(json, Encoding.UTF8, "application/json"), "payload_json");
|
||||||
|
|
||||||
|
var imageBytes = await File.ReadAllBytesAsync(imagePath!, cancellationToken);
|
||||||
|
var imageContent = new ByteArrayContent(imageBytes);
|
||||||
|
imageContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/jpeg");
|
||||||
|
form.Add(imageContent, "files[0]", "poster.jpg");
|
||||||
|
|
||||||
|
response = await client.PostAsync(config.DiscordWebhookUrl, form, cancellationToken);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Send as plain JSON (no image)
|
||||||
|
using var content = new StringContent(json, Encoding.UTF8, "application/json");
|
||||||
|
response = await client.PostAsync(config.DiscordWebhookUrl, content, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
if (!response.IsSuccessStatusCode)
|
if (!response.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -139,10 +139,15 @@ public class PendingNotification
|
|||||||
public NotificationType Type { get; set; }
|
public NotificationType Type { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the image URL.
|
/// Gets or sets the image URL (for public servers).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? ImageUrl { get; set; }
|
public string? ImageUrl { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the local image file path (for attachment-based sending).
|
||||||
|
/// </summary>
|
||||||
|
public string? ImagePath { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the provider IDs JSON.
|
/// Gets or sets the provider IDs JSON.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user