This commit is contained in:
Lightczx
2023-10-26 15:31:55 +08:00
parent f97ad4eac0
commit 0603b24466
14 changed files with 230 additions and 5 deletions

View File

@@ -2877,6 +2877,24 @@ namespace Snap.Hutao.Resource.Localization {
}
}
/// <summary>
/// 查找类似 请输入 Url 的本地化字符串。
/// </summary>
internal static string ViewDialogDailyNoteWebhookUrlInputPlaceholder {
get {
return ResourceManager.GetString("ViewDialogDailyNoteWebhookUrlInputPlaceholder", resourceCulture);
}
}
/// <summary>
/// 查找类似 实时便笺 Webhook Url 的本地化字符串。
/// </summary>
internal static string ViewDialogDailyNoteWebhookUrlTitle {
get {
return ResourceManager.GetString("ViewDialogDailyNoteWebhookUrlTitle", resourceCulture);
}
}
/// <summary>
/// 查找类似 导入祈愿记录 的本地化字符串。
/// </summary>
@@ -3561,6 +3579,15 @@ namespace Snap.Hutao.Resource.Localization {
}
}
/// <summary>
/// 查找类似 配置实时便笺 Webhook Url 完成 的本地化字符串。
/// </summary>
internal static string ViewModelDailyNoteConfigWebhookUrlComplete {
get {
return ResourceManager.GetString("ViewModelDailyNoteConfigWebhookUrlComplete", resourceCulture);
}
}
/// <summary>
/// 查找类似 HoYoLab 账号不支持验证实时便笺 的本地化字符串。
/// </summary>
@@ -4533,6 +4560,33 @@ namespace Snap.Hutao.Resource.Localization {
}
}
/// <summary>
/// 查找类似 在实时便笺刷新后推送到指定的 Webhook 的本地化字符串。
/// </summary>
internal static string ViewPageDailyNoteConfigWebhookDescription {
get {
return ResourceManager.GetString("ViewPageDailyNoteConfigWebhookDescription", resourceCulture);
}
}
/// <summary>
/// 查找类似 配置 Webhook 的本地化字符串。
/// </summary>
internal static string ViewPageDailyNoteConfigWebhookHeader {
get {
return ResourceManager.GetString("ViewPageDailyNoteConfigWebhookHeader", resourceCulture);
}
}
/// <summary>
/// 查找类似 数据互操作 的本地化字符串。
/// </summary>
internal static string ViewPageDailyNoteDataInteropHeader {
get {
return ResourceManager.GetString("ViewPageDailyNoteDataInteropHeader", resourceCulture);
}
}
/// <summary>
/// 查找类似 通知 的本地化字符串。
/// </summary>

View File

@@ -1112,6 +1112,12 @@
<data name="ViewDialogDailyNoteNotificationTransformerNotify" xml:space="preserve">
<value>参量质变仪提醒</value>
</data>
<data name="ViewDialogDailyNoteWebhookUrlInputPlaceholder" xml:space="preserve">
<value>请输入 Url</value>
</data>
<data name="ViewDialogDailyNoteWebhookUrlTitle" xml:space="preserve">
<value>实时便笺 Webhook Url</value>
</data>
<data name="ViewDialogGachaLogImportTitle" xml:space="preserve">
<value>导入祈愿记录</value>
</data>
@@ -1340,6 +1346,9 @@
<data name="ViewModelCultivationProjectInvalidName" xml:space="preserve">
<value>不能添加名称无效的计划</value>
</data>
<data name="ViewModelDailyNoteConfigWebhookUrlComplete" xml:space="preserve">
<value>配置实时便笺 Webhook Url 完成</value>
</data>
<data name="ViewModelDailyNoteHoyolabVerificationUnsupported" xml:space="preserve">
<value>HoYoLab 账号不支持验证实时便笺</value>
</data>
@@ -1664,6 +1673,15 @@
<data name="ViewPageDailyNoteAddEntryToolTip" xml:space="preserve">
<value>添加</value>
</data>
<data name="ViewPageDailyNoteConfigWebhookDescription" xml:space="preserve">
<value>在实时便笺刷新后推送到指定的 Webhook</value>
</data>
<data name="ViewPageDailyNoteConfigWebhookHeader" xml:space="preserve">
<value>配置 Webhook</value>
</data>
<data name="ViewPageDailyNoteDataInteropHeader" xml:space="preserve">
<value>数据互操作</value>
</data>
<data name="ViewPageDailyNoteNotificationHeader" xml:space="preserve">
<value>通知</value>
</data>

View File

@@ -153,7 +153,7 @@ internal abstract partial class DbStoreOptions : ObservableObject, IOptions<DbSt
/// <param name="key">键</param>
/// <param name="value">值</param>
/// <param name="propertyName">属性名称</param>
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))
{

View File

@@ -27,6 +27,7 @@ internal sealed partial class DailyNoteOptions : DbStoreOptions
private NameValue<int>? selectedRefreshTime;
private bool? isReminderNotification;
private bool? isSilentWhenPlayingGame;
private string? webhookUrl;
/// <summary>
/// 刷新时间
@@ -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);
}
}

View File

@@ -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<U
private async ValueTask RefreshDailyNotesCoreAsync(bool forceRefresh)
{
DailyNoteWebhookOperation dailyNoteWebhookOperation = serviceProvider.GetRequiredService<DailyNoteWebhookOperation>();
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<U
// database
entry.UpdateDailyNote(dailyNote);
await dailyNoteDbService.UpdateDailyNoteEntryAsync(entry).ConfigureAwait(false);
await dailyNoteWebhookOperation.TryPostDailyNoteToWebhookAsync(dailyNote).ConfigureAwait(false);
}
}
}

View File

@@ -0,0 +1,35 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
using Snap.Hutao.Web.Request.Builder;
using Snap.Hutao.Web.Request.Builder.Abstraction;
using System.Net.Http;
using WebDailyNote = Snap.Hutao.Web.Hoyolab.Takumi.GameRecord.DailyNote.DailyNote;
namespace Snap.Hutao.Service.DailyNote;
[ConstructorGenerated(ResolveHttpClient = true)]
[HttpClient(HttpClientConfiguration.Default)]
internal sealed partial class DailyNoteWebhookOperation
{
private readonly IHttpRequestMessageBuilderFactory httpRequestMessageBuilderFactory;
private readonly ILogger<DailyNoteWebhookOperation> 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);
}
}

View File

@@ -144,6 +144,7 @@
<None Remove="View\Dialog\CultivatePromotionDeltaBatchDialog.xaml" />
<None Remove="View\Dialog\CultivatePromotionDeltaDialog.xaml" />
<None Remove="View\Dialog\DailyNoteNotificationDialog.xaml" />
<None Remove="View\Dialog\DailyNoteWebhookDialog.xaml" />
<None Remove="View\Dialog\GachaLogImportDialog.xaml" />
<None Remove="View\Dialog\GachaLogRefreshProgressDialog.xaml" />
<None Remove="View\Dialog\GachaLogUrlDialog.xaml" />
@@ -312,6 +313,12 @@
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Page Update="View\Dialog\DailyNoteWebhookDialog.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Page Update="Control\Theme\NumericValue.xaml">
<Generator>MSBuild:Compile</Generator>

View File

@@ -0,0 +1,18 @@
<ContentDialog
x:Class="Snap.Hutao.View.Dialog.DailyNoteWebhookDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:shcm="using:Snap.Hutao.Control.Markup"
Title="{shcm:ResourceString Name=ViewDialogDailyNoteWebhookUrlTitle}"
CloseButtonText="{shcm:ResourceString Name=ContentDialogCancelCloseButtonText}"
DefaultButton="Primary"
PrimaryButtonText="{shcm:ResourceString Name=ContentDialogConfirmPrimaryButtonText}"
Style="{StaticResource DefaultContentDialogStyle}"
mc:Ignorable="d">
<Grid>
<TextBox PlaceholderText="{shcm:ResourceString Name=ViewDialogDailyNoteWebhookUrlInputPlaceholder}" Text="{x:Bind Text, Mode=TwoWay}"/>
</Grid>
</ContentDialog>

View File

@@ -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<ITaskContext>();
}
/// <summary>
/// 获取输入的Url
/// </summary>
/// <returns>输入的结果</returns>
public async ValueTask<ValueResult<bool, string>> GetInputUrlAsync()
{
await taskContext.SwitchToMainThreadAsync();
ContentDialogResult result = await ShowAsync();
return new(result == ContentDialogResult.Primary, Text);
}
}

View File

@@ -13,6 +13,6 @@
mc:Ignorable="d">
<Grid>
<TextBox x:Name="InputText" PlaceholderText="{shcm:ResourceString Name=ViewDialogGachaLogUrlInputPlaceholder}"/>
<TextBox PlaceholderText="{shcm:ResourceString Name=ViewDialogGachaLogUrlInputPlaceholder}" Text="{x:Bind Text, Mode=TwoWay}"/>
</Grid>
</ContentDialog>

View File

@@ -9,6 +9,7 @@ namespace Snap.Hutao.View.Dialog;
/// 祈愿记录Url对话框
/// </summary>
[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);
}
}
}

View File

@@ -159,7 +159,6 @@
</StackPanel>
</cwc:HeaderedContentControl>
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="{shcm:ResourceString Name=ViewPageDailyNoteNotificationHeader}"/>
<cwc:SettingsCard
Description="{shcm:ResourceString Name=ViewPageDailyNoteSlientModeDescription}"
@@ -173,6 +172,14 @@
HeaderIcon="{shcm:FontIcon Glyph=&#xEA8F;}">
<ToggleSwitch Margin="24,0,0,0" IsOn="{Binding Options.IsReminderNotification, Mode=TwoWay}"/>
</cwc:SettingsCard>
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="{shcm:ResourceString Name=ViewPageDailyNoteDataInteropHeader}"/>
<cwc:SettingsCard
Command="{Binding ConfigDailyNoteWebhookUrlCommand}"
Description="{shcm:ResourceString Name=ViewPageDailyNoteConfigWebhookDescription}"
Header="{shcm:ResourceString Name=ViewPageDailyNoteConfigWebhookHeader}"
HeaderIcon="{shcm:FontIcon Glyph=&#xEE94;}"
IsClickEnabled="True"/>
</StackPanel>
</ScrollViewer>
</SplitView.Pane>

View File

@@ -123,4 +123,17 @@ internal sealed partial class DailyNoteViewModel : Abstraction.ViewModel
}
}
}
[Command("ConfigDailyNoteWebhookUrlCommand")]
private async Task ConfigDailyNoteWebhookUrlAsync()
{
DailyNoteWebhookDialog dialog = await contentDialogFactory.CreateInstanceAsync<DailyNoteWebhookDialog>().ConfigureAwait(false);
(bool isOk, string url) = await dialog.GetInputUrlAsync().ConfigureAwait(false);
if (isOk)
{
options.WebhookUrl = url;
infoBarService.Information(SH.ViewModelDailyNoteConfigWebhookUrlComplete);
}
}
}

View File

@@ -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);
}
}
}