diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.Designer.cs b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.Designer.cs
index 824cb508..5f9e467d 100644
--- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.Designer.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.Designer.cs
@@ -2877,6 +2877,24 @@ namespace Snap.Hutao.Resource.Localization {
}
}
+ ///
+ /// 查找类似 请输入 Url 的本地化字符串。
+ ///
+ internal static string ViewDialogDailyNoteWebhookUrlInputPlaceholder {
+ get {
+ return ResourceManager.GetString("ViewDialogDailyNoteWebhookUrlInputPlaceholder", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 实时便笺 Webhook Url 的本地化字符串。
+ ///
+ internal static string ViewDialogDailyNoteWebhookUrlTitle {
+ get {
+ return ResourceManager.GetString("ViewDialogDailyNoteWebhookUrlTitle", resourceCulture);
+ }
+ }
+
///
/// 查找类似 导入祈愿记录 的本地化字符串。
///
@@ -3561,6 +3579,15 @@ namespace Snap.Hutao.Resource.Localization {
}
}
+ ///
+ /// 查找类似 配置实时便笺 Webhook Url 完成 的本地化字符串。
+ ///
+ internal static string ViewModelDailyNoteConfigWebhookUrlComplete {
+ get {
+ return ResourceManager.GetString("ViewModelDailyNoteConfigWebhookUrlComplete", resourceCulture);
+ }
+ }
+
///
/// 查找类似 HoYoLab 账号不支持验证实时便笺 的本地化字符串。
///
@@ -4533,6 +4560,33 @@ namespace Snap.Hutao.Resource.Localization {
}
}
+ ///
+ /// 查找类似 在实时便笺刷新后推送到指定的 Webhook 的本地化字符串。
+ ///
+ internal static string ViewPageDailyNoteConfigWebhookDescription {
+ get {
+ return ResourceManager.GetString("ViewPageDailyNoteConfigWebhookDescription", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 配置 Webhook 的本地化字符串。
+ ///
+ internal static string ViewPageDailyNoteConfigWebhookHeader {
+ get {
+ return ResourceManager.GetString("ViewPageDailyNoteConfigWebhookHeader", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 数据互操作 的本地化字符串。
+ ///
+ internal static string ViewPageDailyNoteDataInteropHeader {
+ get {
+ return ResourceManager.GetString("ViewPageDailyNoteDataInteropHeader", resourceCulture);
+ }
+ }
+
///
/// 查找类似 通知 的本地化字符串。
///
diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx
index 96616973..953f56b6 100644
--- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx
+++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx
@@ -1112,6 +1112,12 @@
参量质变仪提醒
+
+ 请输入 Url
+
+
+ 实时便笺 Webhook Url
+
导入祈愿记录
@@ -1340,6 +1346,9 @@
不能添加名称无效的计划
+
+ 配置实时便笺 Webhook Url 完成
+
HoYoLab 账号不支持验证实时便笺
@@ -1664,6 +1673,15 @@
添加
+
+ 在实时便笺刷新后推送到指定的 Webhook
+
+
+ 配置 Webhook
+
+
+ 数据互操作
+
通知
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Abstraction/DbStoreOptions.cs b/src/Snap.Hutao/Snap.Hutao/Service/Abstraction/DbStoreOptions.cs
index 565201fc..85b95eb9 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/Abstraction/DbStoreOptions.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/Abstraction/DbStoreOptions.cs
@@ -153,7 +153,7 @@ internal abstract partial class DbStoreOptions : ObservableObject, IOptions键
/// 值
/// 属性名称
- protected void SetOption(ref string? storage, string key, string value, [CallerMemberName] string? propertyName = null)
+ protected void SetOption(ref string? storage, string key, string? value, [CallerMemberName] string? propertyName = null)
{
if (!SetProperty(ref storage, value, propertyName))
{
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteOptions.cs b/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteOptions.cs
index 819c8a50..215137e8 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteOptions.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteOptions.cs
@@ -27,6 +27,7 @@ internal sealed partial class DailyNoteOptions : DbStoreOptions
private NameValue? selectedRefreshTime;
private bool? isReminderNotification;
private bool? isSilentWhenPlayingGame;
+ private string? webhookUrl;
///
/// 刷新时间
@@ -122,4 +123,10 @@ internal sealed partial class DailyNoteOptions : DbStoreOptions
get => GetOption(ref isSilentWhenPlayingGame, SettingEntry.DailyNoteSilentWhenPlayingGame);
set => SetOption(ref isSilentWhenPlayingGame, SettingEntry.DailyNoteSilentWhenPlayingGame, value);
}
+
+ public string? WebhookUrl
+ {
+ get => GetOption(ref webhookUrl, SettingEntry.DailyNoteSilentWhenPlayingGame);
+ set => SetOption(ref webhookUrl, SettingEntry.DailyNoteSilentWhenPlayingGame, value);
+ }
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteService.cs b/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteService.cs
index 4d2cdf0b..19e93be7 100644
--- a/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteService.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Service/DailyNote/DailyNoteService.cs
@@ -3,12 +3,15 @@
using CommunityToolkit.Mvvm.Messaging;
using Snap.Hutao.Core.DependencyInjection.Abstraction;
+using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
using Snap.Hutao.Message;
using Snap.Hutao.Model.Entity;
using Snap.Hutao.Service.User;
using Snap.Hutao.ViewModel.User;
using Snap.Hutao.Web.Hoyolab;
using Snap.Hutao.Web.Hoyolab.Takumi.GameRecord;
+using Snap.Hutao.Web.Request.Builder;
+using Snap.Hutao.Web.Request.Builder.Abstraction;
using System.Collections.ObjectModel;
using WebDailyNote = Snap.Hutao.Web.Hoyolab.Takumi.GameRecord.DailyNote.DailyNote;
@@ -108,6 +111,8 @@ internal sealed partial class DailyNoteService : IDailyNoteService, IRecipient();
+
foreach (DailyNoteEntry entry in await dailyNoteDbService.GetDailyNoteEntryIncludeUserListAsync().ConfigureAwait(false))
{
if (!forceRefresh && entry.DailyNote is not null)
@@ -144,6 +149,7 @@ internal sealed partial class DailyNoteService : IDailyNoteService, IRecipient logger;
+ private readonly DailyNoteOptions dailyNoteOptions;
+ private readonly HttpClient httpClient;
+
+ public async ValueTask TryPostDailyNoteToWebhookAsync(WebDailyNote dailyNote, CancellationToken token = default)
+ {
+ string? targetUrl = dailyNoteOptions.WebhookUrl;
+ if (string.IsNullOrEmpty(targetUrl) || !Uri.TryCreate(targetUrl, UriKind.Absolute, out Uri? targetUri))
+ {
+ return;
+ }
+
+ HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create()
+ .SetRequestUri(targetUri)
+ .PostJson(dailyNote);
+
+ await builder.TryCatchSendAsync(httpClient, logger, token).ConfigureAwait(false);
+ }
+}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj
index bdf870c4..7937c061 100644
--- a/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj
+++ b/src/Snap.Hutao/Snap.Hutao/Snap.Hutao.csproj
@@ -144,6 +144,7 @@
+
@@ -312,6 +313,12 @@
+
+
+ MSBuild:Compile
+
+
+
MSBuild:Compile
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/DailyNoteWebhookDialog.xaml b/src/Snap.Hutao/Snap.Hutao/View/Dialog/DailyNoteWebhookDialog.xaml
new file mode 100644
index 00000000..62e6b268
--- /dev/null
+++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/DailyNoteWebhookDialog.xaml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/DailyNoteWebhookDialog.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Dialog/DailyNoteWebhookDialog.xaml.cs
new file mode 100644
index 00000000..3de9132a
--- /dev/null
+++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/DailyNoteWebhookDialog.xaml.cs
@@ -0,0 +1,31 @@
+// Copyright (c) DGP Studio. All rights reserved.
+// Licensed under the MIT license.
+
+using Microsoft.UI.Xaml.Controls;
+
+namespace Snap.Hutao.View.Dialog;
+
+[DependencyProperty("Text", typeof(string))]
+internal sealed partial class DailyNoteWebhookDialog : ContentDialog
+{
+ private readonly ITaskContext taskContext;
+
+ public DailyNoteWebhookDialog(IServiceProvider serviceProvider)
+ {
+ InitializeComponent();
+
+ taskContext = serviceProvider.GetRequiredService();
+ }
+
+ ///
+ /// 获取输入的Url
+ ///
+ /// 输入的结果
+ public async ValueTask> GetInputUrlAsync()
+ {
+ await taskContext.SwitchToMainThreadAsync();
+ ContentDialogResult result = await ShowAsync();
+
+ return new(result == ContentDialogResult.Primary, Text);
+ }
+}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/GachaLogUrlDialog.xaml b/src/Snap.Hutao/Snap.Hutao/View/Dialog/GachaLogUrlDialog.xaml
index 71c3456c..3cc423c8 100644
--- a/src/Snap.Hutao/Snap.Hutao/View/Dialog/GachaLogUrlDialog.xaml
+++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/GachaLogUrlDialog.xaml
@@ -13,6 +13,6 @@
mc:Ignorable="d">
-
+
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Dialog/GachaLogUrlDialog.xaml.cs b/src/Snap.Hutao/Snap.Hutao/View/Dialog/GachaLogUrlDialog.xaml.cs
index 480cd525..2e74c803 100644
--- a/src/Snap.Hutao/Snap.Hutao/View/Dialog/GachaLogUrlDialog.xaml.cs
+++ b/src/Snap.Hutao/Snap.Hutao/View/Dialog/GachaLogUrlDialog.xaml.cs
@@ -9,6 +9,7 @@ namespace Snap.Hutao.View.Dialog;
/// 祈愿记录Url对话框
///
[HighQuality]
+[DependencyProperty("Text", typeof(string))]
internal sealed partial class GachaLogUrlDialog : ContentDialog
{
private readonly ITaskContext taskContext;
@@ -32,8 +33,8 @@ internal sealed partial class GachaLogUrlDialog : ContentDialog
{
await taskContext.SwitchToMainThreadAsync();
ContentDialogResult result = await ShowAsync();
- string url = InputText.Text.TrimEnd("#/log");
+ string url = Text.TrimEnd("#/log");
return new(result == ContentDialogResult.Primary, url);
}
-}
+}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/View/Page/DailyNotePage.xaml b/src/Snap.Hutao/Snap.Hutao/View/Page/DailyNotePage.xaml
index 3ea16f55..b9da657b 100644
--- a/src/Snap.Hutao/Snap.Hutao/View/Page/DailyNotePage.xaml
+++ b/src/Snap.Hutao/Snap.Hutao/View/Page/DailyNotePage.xaml
@@ -159,7 +159,6 @@
-
+
+
+
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/DailyNote/DailyNoteViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/DailyNote/DailyNoteViewModel.cs
index 8bfeac98..69d267fd 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/DailyNote/DailyNoteViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/DailyNote/DailyNoteViewModel.cs
@@ -123,4 +123,17 @@ internal sealed partial class DailyNoteViewModel : Abstraction.ViewModel
}
}
}
+
+ [Command("ConfigDailyNoteWebhookUrlCommand")]
+ private async Task ConfigDailyNoteWebhookUrlAsync()
+ {
+ DailyNoteWebhookDialog dialog = await contentDialogFactory.CreateInstanceAsync().ConfigureAwait(false);
+ (bool isOk, string url) = await dialog.GetInputUrlAsync().ConfigureAwait(false);
+
+ if (isOk)
+ {
+ options.WebhookUrl = url;
+ infoBarService.Information(SH.ViewModelDailyNoteConfigWebhookUrlComplete);
+ }
+ }
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Web/Request/Builder/HttpRequestMessageBuilderExtension.cs b/src/Snap.Hutao/Snap.Hutao/Web/Request/Builder/HttpRequestMessageBuilderExtension.cs
index 263d9825..51cb7539 100644
--- a/src/Snap.Hutao/Snap.Hutao/Web/Request/Builder/HttpRequestMessageBuilderExtension.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Web/Request/Builder/HttpRequestMessageBuilderExtension.cs
@@ -44,4 +44,32 @@ internal static class HttpRequestMessageBuilderExtension
return default;
}
}
+
+ internal static async ValueTask TryCatchSendAsync(this HttpRequestMessageBuilder builder, HttpClient httpClient, ILogger logger, CancellationToken token)
+ {
+ try
+ {
+ HttpResponseMessage message = await httpClient.SendAsync(builder.HttpRequestMessage, token).ConfigureAwait(false);
+ }
+ catch (HttpRequestException ex)
+ {
+ logger.LogWarning(ex, RequestErrorMessage);
+ }
+ catch (IOException ex)
+ {
+ logger.LogWarning(ex, RequestErrorMessage);
+ }
+ catch (JsonException ex)
+ {
+ logger.LogWarning(ex, RequestErrorMessage);
+ }
+ catch (HttpContentSerializationException ex)
+ {
+ logger.LogWarning(ex, RequestErrorMessage);
+ }
+ catch (SocketException ex)
+ {
+ logger.LogWarning(ex, RequestErrorMessage);
+ }
+ }
}
\ No newline at end of file