From 3df45ea6ed7137255a284b2ae724e4bade60334d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B7=E4=B8=AA=E5=90=8D=E5=AD=97=E5=A5=BD=E9=9A=BE?= <25520958+MisakaAldrich@users.noreply.github.com> Date: Fri, 14 Mar 2025 09:50:24 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E7=BB=9F=E8=AE=A1=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=8D=A1=E6=AD=BB=E5=92=8C=E5=BC=82=E5=B8=B8=20(#1293)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../GameTask/LogParse/LogParse.cs | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/BetterGenshinImpact/GameTask/LogParse/LogParse.cs b/BetterGenshinImpact/GameTask/LogParse/LogParse.cs index c381b369..bb9c2289 100644 --- a/BetterGenshinImpact/GameTask/LogParse/LogParse.cs +++ b/BetterGenshinImpact/GameTask/LogParse/LogParse.cs @@ -108,6 +108,7 @@ namespace LogParse { configTask.Fault.ReviveCount++; } + //传送失败,重试 n 次 result = parseBgiLine($@"传送失败,重试 (\d+) 次", logstr); if (result.Item1) @@ -115,19 +116,31 @@ namespace LogParse configTask.Fault.TeleportFailCount = int.Parse(result.Item2[1]); } + //战斗超时结束 if (logstr == "战斗超时结束") { configTask.Fault.BattleTimeoutCount ++; - } + } //重试一次路线或放弃此路线! if (logstr.EndsWith("重试一次路线或放弃此路线!")) { - configTask.Fault.RetryCount++; + configTask.Fault.RetryCount ++; } + //疑似卡死,尝试脱离... + if (logstr == "疑似卡死,尝试脱离...") + { + configTask.Fault.StuckCount ++; + } + //One or more errors occurred + result = parseBgiLine(@"执行脚本时发生异常: ""(.+?)""", logstr); + if (result.Item1) + { + configTask.Fault.ErrCount ++; + } if (logstr.StartsWith("→ 脚本执行结束: \"" + configTask.Name + "\"")) { @@ -241,11 +254,14 @@ namespace LogParse public int ReviveCount { get; set; } = 0; //传送失败次数 public int TeleportFailCount { get; set; } = 0; + //疑似卡死次数 + public int StuckCount { get; set; } = 0; //重试次数 public int RetryCount { get; set; } = 0; //战斗超时 public int BattleTimeoutCount { get; set; } = 0; - + //异常发生次数 + public int ErrCount { get; set; } = 0; } } @@ -401,8 +417,10 @@ namespace LogParse { colConfigList.Add((name: "复活次数", value: task => FormatNumberWithStyle(task.Fault.ReviveCount))); colConfigList.Add((name: "重试次数", value: task => FormatNumberWithStyle(task.Fault.RetryCount))); + colConfigList.Add((name: "疑似卡死次数", value: task => FormatNumberWithStyle(task.Fault.StuckCount))); colConfigList.Add((name: "战斗超时次数", value: task => FormatNumberWithStyle(task.Fault.BattleTimeoutCount))); colConfigList.Add((name: "传送失败次数", value: task => FormatNumberWithStyle(task.Fault.TeleportFailCount))); + colConfigList.Add((name: "异常发生次数", value: task => FormatNumberWithStyle(task.Fault.ErrCount))); } From 76445ab19d9fce704c685d95a77a1b07717761b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=8B=E4=BA=91?= Date: Fri, 14 Mar 2025 11:43:58 +0800 Subject: [PATCH 2/5] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=8D=A2=E9=98=9F?= =?UTF-8?q?=E6=97=B6=E7=88=AC=E4=B8=83=E5=A4=A9=E7=A5=9E=E5=83=8F=E5=AF=BC?= =?UTF-8?q?=E8=87=B4=E6=8D=A2=E9=98=9F=E5=A4=B1=E8=B4=A5=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98=20(#1295)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../GameTask/AutoTrackPath/TpTask.cs | 48 +++++++++++++++---- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/BetterGenshinImpact/GameTask/AutoTrackPath/TpTask.cs b/BetterGenshinImpact/GameTask/AutoTrackPath/TpTask.cs index 8f42142f..145961e7 100644 --- a/BetterGenshinImpact/GameTask/AutoTrackPath/TpTask.cs +++ b/BetterGenshinImpact/GameTask/AutoTrackPath/TpTask.cs @@ -57,6 +57,8 @@ public class TpTask(CancellationToken ct) public async Task TpToStatueOfTheSeven() { await CheckInBigMapUi(); + + // 提前调整至恰当的缩放以更快的传送 if (_tpConfig.MapZoomEnabled) { double currentZoomLevel = GetBigMapZoomLevel(CaptureToRectArea()); @@ -73,22 +75,23 @@ public class TpTask(CancellationToken ct) string? area = _tpConfig.ReviveStatueOfTheSevenArea; double x = _tpConfig.ReviveStatueOfTheSevenPointX; double y = _tpConfig.ReviveStatueOfTheSevenPointY; + GiTpPosition revivePoint = _tpConfig.ReviveStatueOfTheSeven ?? GetNearestGoddess(x, y); if (_tpConfig.IsReviveInNearestStatueOfTheSeven) { var center = GetBigMapCenterPoint(); var giTpPoint = GetNearestGoddess(center.X, center.Y); - if (giTpPoint != null) - { - country = giTpPoint.Country; - area = giTpPoint.Area; - x = giTpPoint.X; - y = giTpPoint.Y; - } + country = giTpPoint.Country; + area = giTpPoint.Area; + x = giTpPoint.X; + y = giTpPoint.Y; + revivePoint = giTpPoint; } + Logger.LogInformation("将传送至 {country} {area} 七天神像", country, area); await Tp(x, y); if (_tpConfig.ShouldMove || _tpConfig.IsReviveInNearestStatueOfTheSeven) { + (x, y) = GetClosestPoint(revivePoint.TranX, revivePoint.TranY, x, y, 5); var waypoint = new Waypoint { X = x, @@ -98,18 +101,45 @@ public class TpTask(CancellationToken ct) }; var waypointForTrack = new WaypointForTrack(waypoint); await new PathExecutor(ct).MoveTo(waypointForTrack); + Simulation.SendInput.SimulateAction(GIActions.Drop); } await Delay((int)(_tpConfig.HpRestoreDuration * 1000), ct); } + /// + /// + /// + /// 传送后实际到达的点X坐标 + /// 传送后实际到达的点Y坐标 + /// 传送点 X 坐标 + /// 传送点 Y 坐标 + /// 期望最终离传送点的距离 + /// + private static (double X, double Y) GetClosestPoint(double tranX, double tranY, double x, double y, double d) + { + double dx = x - tranX; + double dy = y - tranY; + double distanceSquared = dx * dx + dy * dy; + double distance = Math.Sqrt(distanceSquared); + d = d > 0 ? d : 0; + if (distance < d) + { + return (tranX, tranY); + } + double ratio = d / distance; + double px = (x - dx * ratio); + double py = (y - dy * ratio); + return (px, py); + } + /// /// 获取离 x,y 最近的七天神像 /// /// /// /// - private GiTpPosition? GetNearestGoddess(double x, double y) + private GiTpPosition GetNearestGoddess(double x, double y) { GiTpPosition? nearestGiTpPosition = null; double minDistance = double.MaxValue; @@ -123,7 +153,7 @@ public class TpTask(CancellationToken ct) } } // 获取最近的神像位置 - return nearestGiTpPosition; + return nearestGiTpPosition ?? throw new InvalidOperationException("没找到最近的七天神像");; } /// From a662791b6b46203f2905d86c1964cc50d4ed1717 Mon Sep 17 00:00:00 2001 From: DR-lin-eng <52230594+DR-lin-eng@users.noreply.github.com> Date: Fri, 14 Mar 2025 19:39:16 +0800 Subject: [PATCH 3/5] =?UTF-8?q?Tgbot=E6=8E=A8=E9=80=81=E6=9C=BA=E5=99=A8?= =?UTF-8?q?=E4=BA=BA=20(#1296)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add email and websocket notification * fix typos. * refactor(notifiers): 重构邮件和 WebSocket 通知器 - 提升 EmailNotifier 中的 SmtpClient 为类的成员变量,并在构造函数中初始化,优化资源使用 - 改进 WebSocketNotifier 的连接和重连逻辑,提高稳定性 - 优化通知器的错误处理和日志记录,增强可维护性 * Create BarkNotifier.cs * Update NotificationConfig.cs * Update NotificationService.cs * Update CommonSettingsPageViewModel.cs * Add files via upload * Add files via upload * Add files via upload * Update CommonSettingsPage.xaml * Delete BetterGenshinImpact/Service/Notifier/BarkNotifier.cs * Add files via upload * Update BarkNotifier.cs * Update NotificationService.cs * Update CommonSettingsPageViewModel.cs * Update CommonSettingsPage.xaml * Delete BetterGenshinImpact/Service/BarkNotifier.cs * Add files via upload * Add files via upload * Add files via upload * Update CommonSettingsPage.xaml * fix: 回退部分代码,修复了程序崩溃的错误 * fix: remove api.day.app * Update CommonSettingsPageViewModel.cs * Update CommonSettingsPage.xaml * Update CommonSettingsPage.xaml * Update CommonSettingsPageViewModel.cs * Update EmailNotifier.cs * Update EmailNotifier.cs * Update BarkNotifier.cs * 修正并更新前端介绍 * Revert "1" * 修正公益服务器请求兼容性 * Revert "Revert "1"" This reverts commit 8c6effb1 * 新增tg推送但是有发送问题?(疑似我的电脑问题,稍后解决) Signed-off-by: DR-lin-eng <@DR-lin-eng> * feat: Telegram notification and ui. * 修正tgbot推送,修正变量 Signed-off-by: DR-lin-eng <@DR-lin-eng> --------- Signed-off-by: DR-lin-eng <@DR-lin-eng> Co-authored-by: 秋云 Co-authored-by: 禹仔二号 <87601913+wy3057@users.noreply.github.com> Co-authored-by: yuzai <3020834774@qq.com> Co-authored-by: DR-lin-eng <@DR-lin-eng> Co-authored-by: 辉鸭蛋 --- .../Notification/NotificationConfig.cs | 347 +++++++++--------- .../Notification/NotificationService.cs | 89 ++--- .../Service/Notifier/TelegramNotifier.cs | 226 ++++++++++++ .../View/Pages/CommonSettingsPage.xaml | 326 +++++++++++----- .../Pages/CommonSettingsPageViewModel.cs | 15 + 5 files changed, 697 insertions(+), 306 deletions(-) create mode 100644 BetterGenshinImpact/Service/Notifier/TelegramNotifier.cs diff --git a/BetterGenshinImpact/Service/Notification/NotificationConfig.cs b/BetterGenshinImpact/Service/Notification/NotificationConfig.cs index 4ea96fd2..c2d6a92e 100644 --- a/BetterGenshinImpact/Service/Notification/NotificationConfig.cs +++ b/BetterGenshinImpact/Service/Notification/NotificationConfig.cs @@ -1,6 +1,5 @@ -using CommunityToolkit.Mvvm.ComponentModel; using System; -using System.DirectoryServices.ActiveDirectory; +using CommunityToolkit.Mvvm.ComponentModel; namespace BetterGenshinImpact.Service.Notification; @@ -10,187 +9,171 @@ namespace BetterGenshinImpact.Service.Notification; [Serializable] public partial class NotificationConfig : ObservableObject { - - - [ObservableProperty] - private string _notificationEventSubscribe = string.Empty; - - /// - /// - /// - [ObservableProperty] - private bool _webhookEnabled; - - /// - /// - /// - [ObservableProperty] - private string _webhookEndpoint = string.Empty; - - - - /// - /// 是否包含截图 - /// - [ObservableProperty] - private bool _includeScreenShot = true; - - /// - /// windows uwp 通知是否启用 - /// - [ObservableProperty] - private bool _windowsUwpNotificationEnabled = false; - - - // 飞书通知 - /// - /// 飞书通知是否启用 - /// - [ObservableProperty] - private bool _feishuNotificationEnabled = false; - - - /// - /// 飞书通知地址 - /// - [ObservableProperty] - private string _feishuWebhookUrl = string.Empty; - - - // 企业微信通知 - /// - /// 企业微信通知是否启用 - /// - [ObservableProperty] - private bool _workweixinNotificationEnabled = false; - - - /// - /// 企业微信通知通知地址 - /// - [ObservableProperty] - private string _workweixinWebhookUrl = string.Empty; - - [ObservableProperty] - bool _webSocketNotificationEnabled = false; - - [ObservableProperty] - private string _webSocketEndpoint = string.Empty; - - // Email 通知配置 - [ObservableProperty] - private bool _emailNotificationEnabled = false; - - [ObservableProperty] - private string _smtpServer = string.Empty; - - [ObservableProperty] - private int _smtpPort; - - [ObservableProperty] - private string _smtpUsername = string.Empty; - - [ObservableProperty] - private string _smtpPassword = string.Empty; - - [ObservableProperty] - private string _fromEmail = string.Empty; - - [ObservableProperty] - private string _fromName = string.Empty; - - [ObservableProperty] - private string _toEmail = string.Empty; - - /// - /// Bark移动推送通知配置 - /// - [ObservableProperty] - private bool _barkNotificationEnabled = false; - - [ObservableProperty] - private string _barkApiEndpoint = string.Empty; - - [ObservableProperty] - private string _barkDeviceKeys = string.Empty; - - // Bark 通知附加参数配置 - - /// - /// 推送副标题 - /// - [ObservableProperty] - private string _barkSubtitle = string.Empty; - - /// - /// 推送中断级别:critical(重要警告), active(默认值), timeSensitive(时效性通知), passive(仅添加到通知列表) - /// - [ObservableProperty] - private string _barkLevel = "active"; - - /// - /// 通知声音 - /// - [ObservableProperty] - private string _barkSound = "minuet"; - - /// - /// 重要警告的通知音量,取值范围: 0-10 - /// - [ObservableProperty] - private int _barkVolume = 5; - - /// - /// 推送角标,可以是任意数字 - /// - [ObservableProperty] - private int _barkBadge = 1; - - /// - /// 通知铃声重复播放,1为开启 - /// - [ObservableProperty] - private string _barkCall = string.Empty; - - /// - /// iOS14.5以下自动复制推送内容,1为开启 - /// - [ObservableProperty] - private string _barkAutoCopy = string.Empty; - - /// - /// 复制推送时指定复制的内容 - /// - [ObservableProperty] - private string _barkCopy = string.Empty; - - /// - /// 为推送设置自定义图标URL - /// - [ObservableProperty] - private string _barkIcon = string.Empty; - - /// - /// 对消息进行分组,推送将按group分组显示在通知中心中 - /// - [ObservableProperty] - private string _barkGroup = "default"; - - /// - /// 传1保存推送,传其他的不保存推送 - /// - [ObservableProperty] - private string _barkIsArchive = "1"; - - /// - /// 点击推送时跳转的URL - /// - [ObservableProperty] - private string _barkUrl = string.Empty; - /// /// 传"none"时,点击推送不会弹窗 /// - [ObservableProperty] - private string _barkAction = string.Empty; + [ObservableProperty] private string _barkAction = string.Empty; + + [ObservableProperty] private string _barkApiEndpoint = string.Empty; + + /// + /// iOS14.5以下自动复制推送内容,1为开启 + /// + [ObservableProperty] private string _barkAutoCopy = string.Empty; + + /// + /// 推送角标,可以是任意数字 + /// + [ObservableProperty] private int _barkBadge = 1; + + /// + /// 通知铃声重复播放,1为开启 + /// + [ObservableProperty] private string _barkCall = string.Empty; + + [ObservableProperty] private string _barkCiphertext = string.Empty; + + /// + /// 复制推送时指定复制的内容 + /// + [ObservableProperty] private string _barkCopy = string.Empty; + + [ObservableProperty] private string _barkDeviceKeys = string.Empty; + + /// + /// 对消息进行分组,推送将按group分组显示在通知中心中 + /// + [ObservableProperty] private string _barkGroup = "default"; + + /// + /// 为推送设置自定义图标URL + /// + [ObservableProperty] private string _barkIcon = string.Empty; + + /// + /// 传1保存推送,传其他的不保存推送 + /// + [ObservableProperty] private string _barkIsArchive = "1"; + + /// + /// 推送中断级别:critical(重要警告), active(默认值), timeSensitive(时效性通知), passive(仅添加到通知列表) + /// + [ObservableProperty] private string _barkLevel = "active"; + + /// + /// Bark移动推送通知配置 + /// + [ObservableProperty] private bool _barkNotificationEnabled; + + /// + /// 通知声音 + /// + [ObservableProperty] private string _barkSound = "minuet"; + + // Bark 通知附加参数配置 + + /// + /// 推送副标题 + /// + [ObservableProperty] private string _barkSubtitle = string.Empty; + + /// + /// 点击推送时跳转的URL + /// + [ObservableProperty] private string _barkUrl = string.Empty; + + /// + /// 重要警告的通知音量,取值范围: 0-10 + /// + [ObservableProperty] private int _barkVolume = 5; + + // Email 通知配置 + [ObservableProperty] private bool _emailNotificationEnabled; + + + // 飞书通知 + /// + /// 飞书通知是否启用 + /// + [ObservableProperty] private bool _feishuNotificationEnabled; + + + /// + /// 飞书通知地址 + /// + [ObservableProperty] private string _feishuWebhookUrl = string.Empty; + + [ObservableProperty] private string _fromEmail = string.Empty; + + [ObservableProperty] private string _fromName = string.Empty; + + + /// + /// 是否包含截图 + /// + [ObservableProperty] private bool _includeScreenShot = true; + + + [ObservableProperty] private string _notificationEventSubscribe = string.Empty; + + [ObservableProperty] private string _smtpPassword = string.Empty; + + [ObservableProperty] private int _smtpPort; + + [ObservableProperty] private string _smtpServer = string.Empty; + + [ObservableProperty] private string _smtpUsername = string.Empty; + + /// + /// Telegram API基础URL(可选,留空使用官方API) + /// + [ObservableProperty] private string _telegramApiBaseUrl = string.Empty; + + /// + /// Telegram机器人Token + /// + [ObservableProperty] private string _telegramBotToken = string.Empty; + + /// + /// Telegram聊天ID + /// + [ObservableProperty] private string _telegramChatId = string.Empty; + + // Telegram通知 + /// + /// Telegram通知是否启用 + /// + [ObservableProperty] private bool _telegramNotificationEnabled; + + [ObservableProperty] private string _toEmail = string.Empty; + + /// + /// + [ObservableProperty] private bool _webhookEnabled; + + /// + /// + [ObservableProperty] private string _webhookEndpoint = string.Empty; + + [ObservableProperty] private string _webSocketEndpoint = string.Empty; + + [ObservableProperty] private bool _webSocketNotificationEnabled; + + /// + /// windows uwp 通知是否启用 + /// + [ObservableProperty] private bool _windowsUwpNotificationEnabled; + + + // 企业微信通知 + /// + /// 企业微信通知是否启用 + /// + [ObservableProperty] private bool _workweixinNotificationEnabled; + + + /// + /// 企业微信通知通知地址 + /// + [ObservableProperty] private string _workweixinWebhookUrl = string.Empty; } \ No newline at end of file diff --git a/BetterGenshinImpact/Service/Notification/NotificationService.cs b/BetterGenshinImpact/Service/Notification/NotificationService.cs index 6a33ca52..6745ef5b 100644 --- a/BetterGenshinImpact/Service/Notification/NotificationService.cs +++ b/BetterGenshinImpact/Service/Notification/NotificationService.cs @@ -1,18 +1,18 @@ -using BetterGenshinImpact.Service.Notification.Model; -using BetterGenshinImpact.Service.Notifier; -using BetterGenshinImpact.Service.Notifier.Exception; -using BetterGenshinImpact.Service.Notifier.Interface; -using Microsoft.Extensions.Hosting; using System; using System.Drawing; using System.Net.Http; +using System.Text.Json; using System.Threading; using System.Threading.Tasks; using BetterGenshinImpact.GameTask; using BetterGenshinImpact.GameTask.Common; +using BetterGenshinImpact.Service.Notification.Model; using BetterGenshinImpact.Service.Notification.Model.Enum; +using BetterGenshinImpact.Service.Notifier; +using BetterGenshinImpact.Service.Notifier.Exception; +using BetterGenshinImpact.Service.Notifier.Interface; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; -using System.Text.Json; namespace BetterGenshinImpact.Service.Notification; @@ -30,16 +30,6 @@ public class NotificationService : IHostedService InitializeNotifiers(); } - public static NotificationService Instance() - { - if (_instance == null) - { - throw new Exception("Not instantiated"); - } - - return _instance; - } - public Task StartAsync(CancellationToken cancellationToken) { return Task.CompletedTask; @@ -50,12 +40,20 @@ public class NotificationService : IHostedService return Task.CompletedTask; } + public static NotificationService Instance() + { + if (_instance == null) throw new Exception("Not instantiated"); + + return _instance; + } + private void InitializeNotifiers() { if (TaskContext.Instance().Config.NotificationConfig.WebhookEnabled) { - _notifierManager.RegisterNotifier(new WebhookNotifier(NotifyHttpClient, TaskContext.Instance().Config.NotificationConfig.WebhookEndpoint)); + _notifierManager.RegisterNotifier(new WebhookNotifier(NotifyHttpClient, + TaskContext.Instance().Config.NotificationConfig.WebhookEndpoint)); } if (TaskContext.Instance().Config.NotificationConfig.WindowsUwpNotificationEnabled) @@ -65,37 +63,37 @@ public class NotificationService : IHostedService if (TaskContext.Instance().Config.NotificationConfig.FeishuNotificationEnabled) { - _notifierManager.RegisterNotifier(new FeishuNotifier(NotifyHttpClient, TaskContext.Instance().Config.NotificationConfig.FeishuWebhookUrl)); + _notifierManager.RegisterNotifier(new FeishuNotifier(NotifyHttpClient, + TaskContext.Instance().Config.NotificationConfig.FeishuWebhookUrl)); } if (TaskContext.Instance().Config.NotificationConfig.WorkweixinNotificationEnabled) { - _notifierManager.RegisterNotifier(new WorkWeixinNotifier(NotifyHttpClient, TaskContext.Instance().Config.NotificationConfig.WorkweixinWebhookUrl)); + _notifierManager.RegisterNotifier(new WorkWeixinNotifier(NotifyHttpClient, + TaskContext.Instance().Config.NotificationConfig.WorkweixinWebhookUrl)); } - // WebSocket通知初始化 - if (TaskContext.Instance().Config.NotificationConfig.WebSocketNotificationEnabled) + // WebSocket通知初始化 + if (TaskContext.Instance().Config.NotificationConfig.WebSocketNotificationEnabled) + { + var jsonSerializerOptions = new JsonSerializerOptions { - var jsonSerializerOptions = new JsonSerializerOptions - { - PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower, - }; - var cts = new CancellationTokenSource(); - _notifierManager.RegisterNotifier(new WebSocketNotifier( - TaskContext.Instance().Config.NotificationConfig.WebSocketEndpoint, - jsonSerializerOptions, - cts - )); - } + PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower + }; + var cts = new CancellationTokenSource(); + _notifierManager.RegisterNotifier(new WebSocketNotifier( + TaskContext.Instance().Config.NotificationConfig.WebSocketEndpoint, + jsonSerializerOptions, + cts + )); + } - // Bark通知初始化 - if (TaskContext.Instance().Config.NotificationConfig.BarkNotificationEnabled) - { - _notifierManager.RegisterNotifier(new BarkNotifier( - TaskContext.Instance().Config.NotificationConfig.BarkDeviceKeys, - TaskContext.Instance().Config.NotificationConfig.BarkApiEndpoint - )); - } + // Bark通知初始化 + if (TaskContext.Instance().Config.NotificationConfig.BarkNotificationEnabled) + _notifierManager.RegisterNotifier(new BarkNotifier( + TaskContext.Instance().Config.NotificationConfig.BarkDeviceKeys, + TaskContext.Instance().Config.NotificationConfig.BarkApiEndpoint + )); // 邮件通知初始化 if (TaskContext.Instance().Config.NotificationConfig.EmailNotificationEnabled) @@ -110,6 +108,15 @@ public class NotificationService : IHostedService TaskContext.Instance().Config.NotificationConfig.ToEmail )); } + + // Telegram通知初始化 + if (TaskContext.Instance().Config.NotificationConfig.TelegramNotificationEnabled) + _notifierManager.RegisterNotifier(new TelegramNotifier( + NotifyHttpClient, // 使用共享的HttpClient + TaskContext.Instance().Config.NotificationConfig.TelegramBotToken, + TaskContext.Instance().Config.NotificationConfig.TelegramChatId, + TaskContext.Instance().Config.NotificationConfig.TelegramApiBaseUrl + )); } public void RefreshNotifiers() @@ -190,4 +197,4 @@ public class NotificationService : IHostedService { NotifyHttpClient.Dispose(); } -} +} \ No newline at end of file diff --git a/BetterGenshinImpact/Service/Notifier/TelegramNotifier.cs b/BetterGenshinImpact/Service/Notifier/TelegramNotifier.cs new file mode 100644 index 00000000..21bc68cb --- /dev/null +++ b/BetterGenshinImpact/Service/Notifier/TelegramNotifier.cs @@ -0,0 +1,226 @@ +using System; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; +using BetterGenshinImpact.Service.Notification.Model; +using BetterGenshinImpact.Service.Notifier.Exception; +using BetterGenshinImpact.Service.Notifier.Interface; + +namespace BetterGenshinImpact.Service.Notifier; + +public class TelegramNotifier : INotifier, IDisposable +{ + // 永远不更改此URL常量,这是Telegram API的标准URL前缀 + private const string TELEGRAM_API_URL = "https://api.telegram.org/bot"; + private readonly bool _createdHttpClient; + private readonly HttpClient _httpClient; + + private readonly JsonSerializerOptions _jsonSerializerOptions = new() + { + PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower + }; + + /// + /// 创建一个新的Telegram通知器实例 + /// + /// 可选的HttpClient,如果不提供则创建新的 + /// Telegram机器人Token + /// Telegram聊天ID + /// 不再使用,保留参数仅为兼容性 + public TelegramNotifier(HttpClient httpClient = null, string telegramBotToken = "", string telegramChatId = "", + string telegramApiBaseUrl = "") + { + TelegramBotToken = telegramBotToken; + TelegramChatId = telegramChatId; + + if (httpClient != null) + { + _httpClient = httpClient; + _createdHttpClient = false; + } + else + { + _httpClient = new HttpClient(); + _createdHttpClient = true; + _httpClient.Timeout = TimeSpan.FromSeconds(30); + } + + // 忽略自定义API URL,始终使用标准Telegram API URL + TelegramApiBaseUrl = TELEGRAM_API_URL; + } + + /// + /// Telegram机器人Token + /// + public string TelegramBotToken { get; set; } + + /// + /// Telegram聊天ID + /// + public string TelegramChatId { get; set; } + + /// + /// Telegram API基础URL - 内部使用 + /// + private string TelegramApiBaseUrl { get; set; } + + public void Dispose() + { + if (_createdHttpClient) + { + _httpClient?.Dispose(); + } + } + + /// + /// 通知器名称 + /// + public string Name { get; set; } = "Telegram"; + + public async Task SendAsync(BaseNotificationData content) + { + if (string.IsNullOrEmpty(TelegramBotToken)) + { + throw new NotifierException("Telegram bot token is not set"); + } + + if (string.IsNullOrEmpty(TelegramChatId)) + { + throw new NotifierException("Telegram chat ID is not set"); + } + + try + { + var message = content.Message; + var fullMessage = !string.IsNullOrEmpty(message) ? message : ""; + + if (!string.IsNullOrEmpty(fullMessage)) + { + await SendTextMessageAsync(fullMessage); + } + else + { + throw new NotifierException("No message content to send"); + } + } + catch (HttpRequestException ex) + { + throw new NotifierException("Network error sending Telegram notification: " + ex.Message); + } + catch (TaskCanceledException) + { + throw new NotifierException("Telegram API request timed out. Check your internet connection."); + } + catch (NotifierException) + { + throw; + } + catch (System.Exception ex) + { + throw new NotifierException("Error sending Telegram notification: " + ex.Message); + } + } + + private async Task SendTextMessageAsync(string message) + { + // 构建Telegram API URL - 固定格式:https://api.telegram.org/bot{token}/sendMessage + var endpoint = $"{TELEGRAM_API_URL}{TelegramBotToken}/sendMessage"; + + try + { + var jsonContent = new + { + chat_id = TelegramChatId, + text = message, + disable_web_page_preview = true + }; + + var json = JsonSerializer.Serialize(jsonContent, _jsonSerializerOptions); + var content = new StringContent(json, Encoding.UTF8, "application/json"); + + var request = new HttpRequestMessage(HttpMethod.Post, endpoint) + { + Content = content + }; + + request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + request.Headers.UserAgent.Add(new ProductInfoHeaderValue("BetterGenshinImpact", "1.0")); + + var response = await _httpClient.SendAsync(request); + var responseContent = await response.Content.ReadAsStringAsync(); + + if (!response.IsSuccessStatusCode) + { + throw new NotifierException( + $"Telegram message failed with code: {response.StatusCode}, Error: {responseContent}"); + } + + // Check for API errors in the response + var (isSuccess, errorCode, errorDescription) = ValidateApiResponse(responseContent); + + if (!isSuccess) + { + if (errorCode == 400) + { + throw new NotifierException( + "Please send a message to the bot first and check that the chat ID is correct."); + } + + if (errorCode == 401) + { + throw new NotifierException("Telegram bot token is incorrect."); + } + + if (errorCode == 404) + throw new NotifierException( + $"Telegram API not found (404). Please verify your bot token is correct. URL: {endpoint}"); + + throw new NotifierException($"Telegram API error: {errorDescription} (Code: {errorCode})"); + } + } + catch (System.Exception ex) when (!(ex is NotifierException)) + { + throw new NotifierException("Error sending Telegram notification: " + ex.Message); + } + } + + private (bool isSuccess, int errorCode, string errorDescription) ValidateApiResponse(string responseJson) + { + try + { + using (var doc = JsonDocument.Parse(responseJson)) + { + var root = doc.RootElement; + + // Telegram API returns "ok": true for success + if (root.TryGetProperty("ok", out var okElement)) + { + var isOk = okElement.GetBoolean(); + + if (!isOk) + { + var errorDescription = "Unknown Telegram API error"; + if (root.TryGetProperty("description", out var descriptionElement)) + errorDescription = descriptionElement.GetString(); + + var errorCode = 0; + if (root.TryGetProperty("error_code", out var errorCodeElement)) + errorCode = errorCodeElement.GetInt32(); + + return (false, errorCode, errorDescription); + } + + return (true, 0, string.Empty); + } + + return (false, 0, "Invalid API response: 'ok' field missing"); + } + } + catch (JsonException ex) + { + return (false, 0, "Failed to parse API response: " + ex.Message); + } + } +} \ No newline at end of file diff --git a/BetterGenshinImpact/View/Pages/CommonSettingsPage.xaml b/BetterGenshinImpact/View/Pages/CommonSettingsPage.xaml index 0943c6d8..e7a926ee 100644 --- a/BetterGenshinImpact/View/Pages/CommonSettingsPage.xaml +++ b/BetterGenshinImpact/View/Pages/CommonSettingsPage.xaml @@ -15,7 +15,7 @@ FontFamily="{StaticResource TextThemeFontFamily}" Foreground="{DynamicResource TextFillColorPrimaryBrush}" mc:Ignorable="d"> - + - + @@ -636,84 +636,86 @@ - - + + - - + + - + FontTypography="Body" /> - + Foreground="{ui:ThemeResource TextFillColorTertiaryBrush}" /> + - - + + - - + + - + FontTypography="Body" /> - + Foreground="{ui:ThemeResource TextFillColorTertiaryBrush}" /> + - - + + - - + + - + FontTypography="Body" /> + Foreground="{ui:ThemeResource TextFillColorTertiaryBrush}" /> + Margin="0,0,36,0" + ItemsSource="{Binding CountryList}" + SelectedItem="{Binding SelectedCountry}" + MinWidth="120" /> - - + + - - + + - + FontTypography="Body" /> + Foreground="{ui:ThemeResource TextFillColorTertiaryBrush}" /> + Margin="0,0,36,0" + ItemsSource="{Binding Areas}" + SelectedItem="{Binding SelectedArea}" + MinWidth="120" /> - + @@ -773,7 +775,7 @@ Command="{Binding ImportLocalScriptsRepoZipCommand}" Content="导入" /> - + @@ -800,16 +802,16 @@ Text="使按键绑定设置对外部脚本生效" TextWrapping="Wrap" /> + Grid.RowSpan="2" + Grid.Column="1" + Margin="0,0,36,0" + IsChecked="{Binding Config.KeyBindingsConfig.GlobalKeyMappingEnabled}" /> - - + + @@ -861,7 +863,7 @@ Margin="0,0,36,0" IsChecked="{Binding Config.OtherConfig.RestoreFocusOnLostEnabled, Mode=TwoWay}" /> - + - + @@ -1693,7 +1695,7 @@ Text="{Binding Config.NotificationConfig.BarkApiEndpoint, Mode=TwoWay}" TextWrapping="NoWrap" /> - + @@ -1713,6 +1715,7 @@ Foreground="{ui:ThemeResource TextFillColorTertiaryBrush}" Text="多个设备使用逗号、分号或空格分隔 (请使用英文输入法)" TextWrapping="Wrap" /> + + TextWrapping="Wrap" /> - + @@ -1741,18 +1744,22 @@ - + + + + + + - + @@ -1770,18 +1777,20 @@ - + + + + + - + @@ -1810,7 +1819,7 @@ Text="{Binding Config.NotificationConfig.BarkGroup, Mode=TwoWay}" TextWrapping="NoWrap" /> - + @@ -1830,14 +1839,17 @@ Foreground="{ui:ThemeResource TextFillColorTertiaryBrush}" Text="传1保存推送,传其他不保存" TextWrapping="Wrap" /> - + + + + @@ -1896,6 +1908,154 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + \ No newline at end of file diff --git a/BetterGenshinImpact/ViewModel/Pages/CommonSettingsPageViewModel.cs b/BetterGenshinImpact/ViewModel/Pages/CommonSettingsPageViewModel.cs index 31c03b9f..4aa0cdb1 100644 --- a/BetterGenshinImpact/ViewModel/Pages/CommonSettingsPageViewModel.cs +++ b/BetterGenshinImpact/ViewModel/Pages/CommonSettingsPageViewModel.cs @@ -294,6 +294,21 @@ public partial class CommonSettingsPageViewModel : ViewModel } } + [RelayCommand] + private async Task OnTestTelegramNotification() + { + var res = await _notificationService.TestNotifierAsync(); + if(res.IsSuccess) + { + Toast.Success(res.Message); + } + else + { + Toast.Error(res.Message); + } + } + + [RelayCommand] private void ImportLocalScriptsRepoZip() { From 45fc9fe7f4b849324a51d5ec1665ab41a72ead9d Mon Sep 17 00:00:00 2001 From: DR-lin-eng <52230594+DR-lin-eng@users.noreply.github.com> Date: Sat, 15 Mar 2025 10:33:13 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=9B=BE=E7=89=87?= =?UTF-8?q?=E4=BD=9C=E4=B8=BAemail=E9=99=84=E4=BB=B6=E5=8F=91=E9=80=81?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=20(#1298)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: DR-lin-eng <@DR-lin-eng> --- .../Service/Notifier/EmailNotifier.cs | 138 ++++++++++++------ .../View/Pages/CommonSettingsPage.xaml | 42 +++--- 2 files changed, 118 insertions(+), 62 deletions(-) diff --git a/BetterGenshinImpact/Service/Notifier/EmailNotifier.cs b/BetterGenshinImpact/Service/Notifier/EmailNotifier.cs index b9b694df..e43d7493 100644 --- a/BetterGenshinImpact/Service/Notifier/EmailNotifier.cs +++ b/BetterGenshinImpact/Service/Notifier/EmailNotifier.cs @@ -1,3 +1,6 @@ +using System.Drawing.Imaging; +using System.IO; +using System.Net; using System.Net.Mail; using System.Text; using System.Threading.Tasks; @@ -9,23 +12,15 @@ namespace BetterGenshinImpact.Service.Notifier { public class EmailNotifier : INotifier { - public string Name { get; set; } = "Email"; - - // SMTP服务器配置 - private readonly string _smtpServer; - private readonly int _smtpPort; - private readonly string _smtpUsername; - private readonly string _smtpPassword; - // 发件人配置 private readonly string _fromEmail; private readonly string _fromName; - - // 收件人邮箱 - public string ToEmail { get; set; } + private readonly string _smtpPassword; + private readonly int _smtpPort; - // 提升 SmtpClient 为类的成员变量 - private readonly SmtpClient _smtpClient; + // SMTP服务器配置 + private readonly string _smtpServer; + private readonly string _smtpUsername; public EmailNotifier( string smtpServer, @@ -44,14 +39,15 @@ namespace BetterGenshinImpact.Service.Notifier _fromName = fromName; ToEmail = toEmail; - // 在构造函数中初始化 SmtpClient - _smtpClient = new SmtpClient(_smtpServer, _smtpPort) - { - Credentials = new System.Net.NetworkCredential(_smtpUsername, _smtpPassword), - EnableSsl = true - }; + // 忽略SSL证书验证错误 + ServicePointManager.ServerCertificateValidationCallback = + delegate { return true; }; } + // 收件人邮箱 + public string ToEmail { get; set; } + public string Name { get; set; } = "Email"; + public async Task SendAsync(BaseNotificationData content) { if (string.IsNullOrEmpty(ToEmail)) @@ -59,24 +55,78 @@ namespace BetterGenshinImpact.Service.Notifier throw new NotifierException("收件人邮箱地址为空"); } - try + // 创建一个新的SmtpClient实例(不复用) + using (var smtpClient = new SmtpClient()) { - using var mailMessage = new MailMessage + try { - From = new MailAddress(_fromEmail, _fromName), - Subject = FormatEmailSubject(content), - Body = FormatEmailBody(content), - IsBodyHtml = true - }; - - mailMessage.To.Add(ToEmail); + // 配置SMTP客户端 + smtpClient.Host = _smtpServer; + smtpClient.Port = _smtpPort; + smtpClient.EnableSsl = true; + smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network; + smtpClient.UseDefaultCredentials = false; + smtpClient.Credentials = new NetworkCredential(_smtpUsername, _smtpPassword); + smtpClient.Timeout = 30000; // 30秒超时 - // 使用成员变量 _smtpClient 发送邮件 - await _smtpClient.SendMailAsync(mailMessage); - } - catch (System.Exception ex) - { - throw new NotifierException($"发送邮件失败: {ex.Message}"); + // 创建邮件 + using (var mailMessage = new MailMessage()) + { + mailMessage.From = new MailAddress(_fromEmail, _fromName); + mailMessage.To.Add(ToEmail); + mailMessage.Subject = FormatEmailSubject(content); + mailMessage.Body = FormatEmailBody(content); + mailMessage.IsBodyHtml = true; + mailMessage.BodyEncoding = Encoding.UTF8; + mailMessage.SubjectEncoding = Encoding.UTF8; + + // 添加图片附件(如果存在) + if (content.Screenshot != null) + { + var tempPath = Path.GetTempFileName() + ".jpg"; + try + { + // 保存图片到临时文件 + content.Screenshot.Save(tempPath, ImageFormat.Jpeg); + + // 从文件添加附件 + var attachment = new Attachment(tempPath); + mailMessage.Attachments.Add(attachment); + + // 发送邮件 + await smtpClient.SendMailAsync(mailMessage); + + // 清理附件和临时文件 + attachment.Dispose(); + if (File.Exists(tempPath)) File.Delete(tempPath); + } + catch (System.Exception ex) + { + // 尝试清理临时文件 + try + { + if (File.Exists(tempPath)) File.Delete(tempPath); + } + catch + { + /* 忽略清理错误 */ + } + + throw new NotifierException($"发送邮件失败: {ex.Message}"); + } + } + else + { + // 没有图片时直接发送 + await smtpClient.SendMailAsync(mailMessage); + } + } + } + catch (System.Exception ex) + { + var errorMessage = $"发送邮件失败: {ex.Message}"; + throw new NotifierException(errorMessage); + } } } @@ -89,23 +139,29 @@ namespace BetterGenshinImpact.Service.Notifier private string FormatEmailBody(BaseNotificationData content) { var builder = new StringBuilder(); - builder.AppendLine(""); - + builder.AppendLine(""); + // 添加通知标题 - builder.AppendLine("

通知详情

"); - + builder.AppendLine("

通知详情

"); + // 添加通知内容 foreach (var prop in content.GetType().GetProperties()) { + // 跳过Screenshot属性,它会单独处理 + if (prop.Name == "Screenshot") + continue; + var value = prop.GetValue(content); if (value != null) { - builder.AppendLine($"

{prop.Name}: {value}

"); + builder.AppendFormat("

{0}: {1}

", prop.Name, value); } } - + + // 添加提示信息 + builder.AppendLine("

如有截图,请查看附件。

"); builder.AppendLine(""); return builder.ToString(); } } -} +} \ No newline at end of file diff --git a/BetterGenshinImpact/View/Pages/CommonSettingsPage.xaml b/BetterGenshinImpact/View/Pages/CommonSettingsPage.xaml index e7a926ee..59487987 100644 --- a/BetterGenshinImpact/View/Pages/CommonSettingsPage.xaml +++ b/BetterGenshinImpact/View/Pages/CommonSettingsPage.xaml @@ -1455,7 +1455,7 @@ - + - - - - - + MinWidth="120"> + + + + @@ -1779,15 +1779,15 @@ Foreground="{ui:ThemeResource TextFillColorTertiaryBrush}" Text="选择通知声音" TextWrapping="Wrap" /> - - + MinWidth="120"> + - + @@ -1840,13 +1840,13 @@ Text="传1保存推送,传其他不保存" TextWrapping="Wrap" /> + Grid.RowSpan="2" + Grid.Column="1" + MinWidth="180" + MaxWidth="800" + Margin="0,0,36,0" + SelectedValue="{Binding Config.NotificationConfig.BarkIsArchive, Mode=TwoWay}" + SelectedValuePath="Tag"> From f7903f8e9bf373c917d38567ee1f23b03a6f83f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A6=B9=E4=BB=94=E4=BA=8C=E5=8F=B7?= <87601913+wy3057@users.noreply.github.com> Date: Sat, 15 Mar 2025 10:33:33 +0800 Subject: [PATCH 5/5] =?UTF-8?q?webhook=E6=B7=BB=E5=8A=A0=E4=BA=86sendto?= =?UTF-8?q?=E5=8F=91=E9=80=81=E5=AF=B9=E8=B1=A1=EF=BC=8C=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E4=BA=86webhook=E9=80=9A=E7=9F=A5ui=E6=98=BE=E7=A4=BA=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E9=97=AE=E9=A2=98=EF=BC=8C=E4=BF=AE=E5=A4=8D=E4=BA=86?= =?UTF-8?q?websocket=E6=9C=8D=E5=8A=A1=E7=AB=AF=E9=94=99=E8=AF=AF=E5=85=B3?= =?UTF-8?q?=E9=97=AD=E9=93=BE=E6=8E=A5=E9=97=AE=E9=A2=98=20(#1300)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 新增图片作为email附件发送功能 * feat(notification): 为 WebhookNotifier 添加 send_to 功能 - 在 WebhookNotifier 类中添加 send_to 属性 - 修改 TransformData 方法,增加 send_to 字段 - 在 NotificationConfig 中添加 webhook_endpoint 和 websocket_endpoint 属性 * refactor(WebhookNotifier): 添加 send_to 属性并调整访问修饰符 * refactor(notification): 重构 WebhookNotifier 并更新 NotificationConfig - 在 NotificationConfig 中添加 WebhookSendTo 属性 - 重构 WebhookNotifier 构造函数,使用 NotificationConfig 对象进行初始化 - 更新 WebhookNotifier 发送逻辑,使用新的配置属性 * feat: add webhook ui. * refactor(WebhookNotifier): 重构 TransformData 方法以优化数据结构- 将 notification_data 的内容合并到外层字典,以便于 webhook 接收端获取数据- 新增 event、result、timestamp 等字段,使数据结构 * fix(WebSocketNotifier): 添加消息发送后关闭连接的功能 - 在 SendAsync 方法中添加了 CloseAsync() 调用,确保消息发送后关闭 WebSocket 连接 - 此修改解决了消息发送后未关闭连接的问题,提高了资源利用率和系统稳定性 * fix: implement unified webhook ui * fix: typos. --------- Co-authored-by: DR-lin-eng <@DR-lin-eng> Co-authored-by: 秋云 --- .../Notification/NotificationConfig.cs | 3 ++ .../Notification/NotificationService.cs | 2 +- .../Service/Notifier/WebSocketNotifier.cs | 5 +- .../Service/Notifier/WebhookNotifier.cs | 30 +++++++++--- .../View/Pages/CommonSettingsPage.xaml | 49 +++++++++++++------ .../Pages/CommonSettingsPageViewModel.cs | 22 +++------ 6 files changed, 74 insertions(+), 37 deletions(-) diff --git a/BetterGenshinImpact/Service/Notification/NotificationConfig.cs b/BetterGenshinImpact/Service/Notification/NotificationConfig.cs index c2d6a92e..e4b30dea 100644 --- a/BetterGenshinImpact/Service/Notification/NotificationConfig.cs +++ b/BetterGenshinImpact/Service/Notification/NotificationConfig.cs @@ -154,7 +154,10 @@ public partial class NotificationConfig : ObservableObject /// /// [ObservableProperty] private string _webhookEndpoint = string.Empty; + + [ObservableProperty] private string _webhookSendTo = string.Empty; // 修改属性名 + [ObservableProperty] private string _webSocketEndpoint = string.Empty; [ObservableProperty] private bool _webSocketNotificationEnabled; diff --git a/BetterGenshinImpact/Service/Notification/NotificationService.cs b/BetterGenshinImpact/Service/Notification/NotificationService.cs index 6745ef5b..952087eb 100644 --- a/BetterGenshinImpact/Service/Notification/NotificationService.cs +++ b/BetterGenshinImpact/Service/Notification/NotificationService.cs @@ -53,7 +53,7 @@ public class NotificationService : IHostedService if (TaskContext.Instance().Config.NotificationConfig.WebhookEnabled) { _notifierManager.RegisterNotifier(new WebhookNotifier(NotifyHttpClient, - TaskContext.Instance().Config.NotificationConfig.WebhookEndpoint)); + TaskContext.Instance().Config.NotificationConfig)); } if (TaskContext.Instance().Config.NotificationConfig.WindowsUwpNotificationEnabled) diff --git a/BetterGenshinImpact/Service/Notifier/WebSocketNotifier.cs b/BetterGenshinImpact/Service/Notifier/WebSocketNotifier.cs index 55a2d512..347e5f5a 100644 --- a/BetterGenshinImpact/Service/Notifier/WebSocketNotifier.cs +++ b/BetterGenshinImpact/Service/Notifier/WebSocketNotifier.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Net.WebSockets; using System.Text.Json; using System.Threading; @@ -53,6 +53,7 @@ namespace BetterGenshinImpact.Service.Notifier var json = JsonSerializer.Serialize(notificationData, _jsonSerializerOptions); var buffer = System.Text.Encoding.UTF8.GetBytes(json); await _webSocket.SendAsync(new ArraySegment(buffer), WebSocketMessageType.Text, true, _cts.Token); + await CloseAsync(); // 添加关闭连接的代码 } catch (WebSocketException ex) { @@ -82,4 +83,4 @@ namespace BetterGenshinImpact.Service.Notifier await SendAsync(notificationData); } } -} +} \ No newline at end of file diff --git a/BetterGenshinImpact/Service/Notifier/WebhookNotifier.cs b/BetterGenshinImpact/Service/Notifier/WebhookNotifier.cs index e6b6483f..d8e702ac 100644 --- a/BetterGenshinImpact/Service/Notifier/WebhookNotifier.cs +++ b/BetterGenshinImpact/Service/Notifier/WebhookNotifier.cs @@ -1,10 +1,13 @@ -using BetterGenshinImpact.Service.Notifier.Exception; +using BetterGenshinImpact.Service.Notifier.Exception; using BetterGenshinImpact.Service.Notifier.Interface; using System.Net.Http; using System.Text; using System.Text.Json; using System.Threading.Tasks; using BetterGenshinImpact.Service.Notification.Model; +using System.Collections.Generic; +using BetterGenshinImpact.Service.Notification; // 添加对 System.Collections.Generic 命名空间的引用 +using BetterGenshinImpact.Service.Notification; // 添加对 NotificationConfig 类型的引用 namespace BetterGenshinImpact.Service.Notifier; @@ -14,6 +17,9 @@ public class WebhookNotifier : INotifier public string Endpoint { get; set; } + // 添加 send_to 属性 + private string SendTo { get; set; } + private readonly HttpClient _httpClient; private readonly JsonSerializerOptions _jsonSerializerOptions = new() @@ -21,10 +27,12 @@ public class WebhookNotifier : INotifier PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower, }; - public WebhookNotifier(HttpClient httpClient, string endpoint = "") + public WebhookNotifier(HttpClient httpClient, NotificationConfig config) { + _httpClient = httpClient; - Endpoint = endpoint; + Endpoint = config.WebhookEndpoint; + SendTo = config.WebhookSendTo; // 初始化 send_to 属性 } public async Task SendAsync(BaseNotificationData content) @@ -53,11 +61,21 @@ public class WebhookNotifier : INotifier } } - private StringContent TransformData(BaseNotificationData notificationData) { - // using object type here so it serializes the interface correctly - var serializedData = JsonSerializer.Serialize(notificationData, _jsonSerializerOptions); + // 使用 SendTo 属性来设置 send_to 字段,并将 notification_data 的内容合并到外层字典 + var dataToSend = new Dictionary + { + { "send_to", SendTo }, + { "event", notificationData.Event }, + { "result", notificationData.Result }, + { "timestamp", notificationData.Timestamp }, + { "screenshot", notificationData.Screenshot }, + { "message", notificationData.Message }, + { "data", notificationData.Data } + }; + + var serializedData = JsonSerializer.Serialize(dataToSend, _jsonSerializerOptions); return new StringContent(serializedData, Encoding.UTF8, "application/json"); } diff --git a/BetterGenshinImpact/View/Pages/CommonSettingsPage.xaml b/BetterGenshinImpact/View/Pages/CommonSettingsPage.xaml index 59487987..c2f66aa7 100644 --- a/BetterGenshinImpact/View/Pages/CommonSettingsPage.xaml +++ b/BetterGenshinImpact/View/Pages/CommonSettingsPage.xaml @@ -979,7 +979,7 @@ + + + + + + + + + + + + + @@ -1038,18 +1066,11 @@ TextWrapping="Wrap" /> - + Content="发送"/> @@ -1713,7 +1734,7 @@ CountryList { get; } = new(); public ObservableCollection Areas { get; } = new(); private readonly TpConfig _tpConfig = TaskContext.Instance().Config.TpConfig; @@ -200,14 +193,15 @@ public partial class CommonSettingsPageViewModel : ViewModel [RelayCommand] private async Task OnTestWebhook() { - IsLoading = true; - WebhookStatus = string.Empty; - var res = await _notificationService.TestNotifierAsync(); - - WebhookStatus = res.Message; - - IsLoading = false; + if(res.IsSuccess) + { + Toast.Success(res.Message); + } + else + { + Toast.Error(res.Message); + } } [RelayCommand]