Implement NotifyOnStatusChange feature for nodes and enhance Telegram notifications
- Added `NotifyOnStatusChange` property to the `Node` class and related DTOs to allow individual node configuration for status change notifications. - Updated `NodeHealthCheckService` to send Telegram notifications to admins when a node's status changes, based on the new property. - Enhanced the `ITelegramNotifier` interface with a method for notifying admins about node status changes. - Modified the frontend to include a checkbox for `NotifyOnStatusChange` in the node editing dialog, allowing admins to easily configure this setting. - Updated API documentation to reflect the new `notifyOnStatusChange` parameter in the node update endpoint. - Added tests to ensure the correct behavior of the new feature and its integration with existing functionality.
This commit is contained in:
@@ -55,6 +55,7 @@ public static class NodeEndpoints
|
||||
body.BaseAddress,
|
||||
body.Location,
|
||||
body.IsEnabled,
|
||||
body.NotifyOnStatusChange,
|
||||
body.Username,
|
||||
body.Password
|
||||
);
|
||||
@@ -98,6 +99,7 @@ public sealed record UpdateNodeBody(
|
||||
string BaseAddress,
|
||||
string? Location,
|
||||
bool IsEnabled,
|
||||
bool NotifyOnStatusChange,
|
||||
string? Username,
|
||||
string? Password
|
||||
);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
using PnvPanel.Application.Common.Interfaces;
|
||||
using PnvPanel.Domain.Billing;
|
||||
using PnvPanel.Domain.Nodes;
|
||||
using PnvPanel.Domain.Support;
|
||||
using PnvPanel.Infrastructure.Telegram;
|
||||
using Telegram.Bot;
|
||||
@@ -358,6 +359,48 @@ internal sealed class TelegramNotifier(
|
||||
}
|
||||
}
|
||||
|
||||
public async Task NotifyAdminsNodeStatusChangedAsync(
|
||||
Guid nodeId,
|
||||
string nodeName,
|
||||
NodeStatus status,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(options.Value.BotToken))
|
||||
return;
|
||||
|
||||
var emoji = status == NodeStatus.Online ? "✅" : "🔴";
|
||||
var statusLabel = status == NodeStatus.Online ? "снова в сети" : "недоступна";
|
||||
var text = $"{emoji} Нода <b>{Escape(nodeName)}</b> {statusLabel}.";
|
||||
|
||||
InlineKeyboardMarkup? keyboard = null;
|
||||
if (!string.IsNullOrWhiteSpace(options.Value.PublicSiteUrl))
|
||||
{
|
||||
var url = $"{options.Value.PublicSiteUrl.TrimEnd('/')}/admin/nodes";
|
||||
keyboard = new InlineKeyboardMarkup(
|
||||
new[] { InlineKeyboardButton.WithUrl("🌐 Открыть на сайте", url) }
|
||||
);
|
||||
}
|
||||
|
||||
foreach (var adminId in options.Value.ParseAdminTelegramUserIds())
|
||||
{
|
||||
try
|
||||
{
|
||||
await botClient.SendMessage(
|
||||
adminId,
|
||||
text,
|
||||
parseMode: ParseMode.Html,
|
||||
replyMarkup: keyboard,
|
||||
cancellationToken: cancellationToken
|
||||
);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Админ мог не запускать бота (нет чата с ботом) — пропускаем, не валим команду.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string Escape(string text) =>
|
||||
text.Replace("&", "&").Replace("<", "<").Replace(">", ">");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user