This commit is contained in:
DismissedLight
2023-02-11 12:32:00 +08:00
parent d7dd8c6f0d
commit 818365b816
19 changed files with 147 additions and 206 deletions

View File

@@ -8,6 +8,7 @@ using Snap.Hutao.Extension;
using Snap.Hutao.Web.Hoyolab.DynamicSecret;
using System.Collections.Immutable;
using System.IO;
using System.Text.Encodings.Web;
using System.Text.Json.Serialization.Metadata;
using Windows.ApplicationModel;
@@ -87,7 +88,7 @@ internal static class CoreEnvironment
public static readonly JsonSerializerOptions JsonOptions = new()
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
Encoder = new JsonTextEncoder(),
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
PropertyNameCaseInsensitive = true,
WriteIndented = true,
TypeInfoResolver = new DefaultJsonTypeInfoResolver()

View File

@@ -37,6 +37,11 @@ internal static class Activation
/// <returns>是否提升了权限</returns>
public static bool GetElevated()
{
if (System.Diagnostics.Debugger.IsAttached)
{
return true;
}
using (WindowsIdentity identity = WindowsIdentity.GetCurrent())
{
WindowsPrincipal principal = new(identity);

View File

@@ -6,6 +6,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mxi="using:Microsoft.Xaml.Interactivity"
xmlns:shcb="using:Snap.Hutao.Control.Behavior"
xmlns:shcm="using:Snap.Hutao.Control.Markup"
xmlns:shv="using:Snap.Hutao.ViewModel"
mc:Ignorable="d">
@@ -28,7 +29,7 @@
Margin="12,0,0,0"
VerticalAlignment="Center"
Style="{StaticResource CaptionTextBlockStyle}"
Text="选择账号并启动"
Text="{shcm:ResourceString Name=LaunchGameTitle}"
TextWrapping="NoWrap"/>
</Grid>
@@ -44,7 +45,7 @@
<TextBlock
Opacity="0.8"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{Binding AttachUid, TargetNullValue=该账号尚未绑定 UID}"/>
Text="{Binding AttachUid, TargetNullValue={shcm:ResourceString Name=ViewPageLaunchGameSwitchAccountAttachUidNull}}"/>
</StackPanel>
</Grid>
</DataTemplate>
@@ -56,6 +57,6 @@
Margin="16"
HorizontalAlignment="Stretch"
Command="{Binding LaunchCommand}"
Content="启动游戏"/>
Content="{shcm:ResourceString Name=ViewPageLaunchGameAction}"/>
</Grid>
</Window>

View File

@@ -41,4 +41,17 @@ public class CultivateEntry : ItemBase
/// 实体
/// </summary>
public List<CultivateItem> Items { get; set; } = default!;
/// <summary>
/// 是否为今日的材料
/// </summary>
public bool IsToday { get => Items.Any(i => i.IsToday); }
/// <summary>
/// 星期中的日期
/// </summary>
public DaysOfWeek DaysOfWeek
{
get => Items.FirstOrDefault(i => i.DaysOfWeek != DaysOfWeek.Any)?.DaysOfWeek ?? DaysOfWeek.Any;
}
}

View File

@@ -24,9 +24,6 @@ public class CultivateItem : ObservableObject
Inner = inner;
Entity = entity;
isFinished = Entity.IsFinished;
IsToday = inner.IsTodaysItem();
FinishStateCommand = new RelayCommand(FlipIsFinished);
}
/// <summary>
@@ -39,11 +36,6 @@ public class CultivateItem : ObservableObject
/// </summary>
public Entity.CultivateItem Entity { get; }
/// <summary>
/// 调整完成状态命令
/// </summary>
public ICommand FinishStateCommand { get; }
/// <summary>
/// 是否完成此项
/// </summary>
@@ -61,15 +53,10 @@ public class CultivateItem : ObservableObject
/// <summary>
/// 是否为今日物品
/// </summary>
public bool IsToday { get; }
public bool IsToday { get => Inner.IsTodaysItem(); }
/// <summary>
/// 对应背包物品的个数
/// 星期中的日期
/// </summary>
public uint InventoryItemCount { get; set; }
private void FlipIsFinished()
{
IsFinished = !IsFinished;
}
public DaysOfWeek DaysOfWeek { get => Inner.GetDaysOfWeek(); }
}

View File

@@ -0,0 +1,35 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Core.Annotation;
namespace Snap.Hutao.Model.Binding.Cultivation;
/// <summary>
/// 游戏内星期中的天
/// </summary>
public enum DaysOfWeek
{
/// <summary>
/// 任意
/// </summary>
Any,
/// <summary>
/// 周一/周四/周日
/// </summary>
[LocalizationKey("ModelBindingCultivationDaysOfWeek14")]
MondayAndThursday,
/// <summary>
/// 周二/周五/周日
/// </summary>
[LocalizationKey("ModelBindingCultivationDaysOfWeek25")]
TuesdayAndFriday,
/// <summary>
/// 周三/周六/周日
/// </summary>
[LocalizationKey("ModelBindingCultivationDaysOfWeek36")]
WednesdayAndSaturday,
}

View File

@@ -143,4 +143,28 @@ public class Material
_ => false,
};
}
/// <summary>
/// 获取物品对应的 DaysOfWeek
/// </summary>
/// <returns>DaysOfWeek</returns>
public Binding.Cultivation.DaysOfWeek GetDaysOfWeek()
{
if (MondayThursdayItems.Contains(Id))
{
return Binding.Cultivation.DaysOfWeek.MondayAndThursday;
}
if (TuesdayFridayItems.Contains(Id))
{
return Binding.Cultivation.DaysOfWeek.TuesdayAndFriday;
}
if (WednesdaySaturdayItems.Contains(Id))
{
return Binding.Cultivation.DaysOfWeek.WednesdayAndSaturday;
}
return Binding.Cultivation.DaysOfWeek.Any;
}
}

View File

@@ -267,6 +267,42 @@ namespace Snap.Hutao.Resource.Localization {
}
}
/// <summary>
/// 查找类似 选择账号并启动 的本地化字符串。
/// </summary>
internal static string LaunchGameTitle {
get {
return ResourceManager.GetString("LaunchGameTitle", resourceCulture);
}
}
/// <summary>
/// 查找类似 周一/周四/周日 的本地化字符串。
/// </summary>
internal static string ModelBindingCultivationDaysOfWeek14 {
get {
return ResourceManager.GetString("ModelBindingCultivationDaysOfWeek14", resourceCulture);
}
}
/// <summary>
/// 查找类似 周二/周五/周日 的本地化字符串。
/// </summary>
internal static string ModelBindingCultivationDaysOfWeek25 {
get {
return ResourceManager.GetString("ModelBindingCultivationDaysOfWeek25", resourceCulture);
}
}
/// <summary>
/// 查找类似 周三/周六/周日 的本地化字符串。
/// </summary>
internal static string ModelBindingCultivationDaysOfWeek36 {
get {
return ResourceManager.GetString("ModelBindingCultivationDaysOfWeek36", resourceCulture);
}
}
/// <summary>
/// 查找类似 第 {0} 层 的本地化字符串。
/// </summary>

View File

@@ -186,6 +186,18 @@
<data name="FilePickerImportCommit" xml:space="preserve">
<value>导入</value>
</data>
<data name="LaunchGameTitle" xml:space="preserve">
<value>选择账号并启动</value>
</data>
<data name="ModelBindingCultivationDaysOfWeek14" xml:space="preserve">
<value>周一/周四/周日</value>
</data>
<data name="ModelBindingCultivationDaysOfWeek25" xml:space="preserve">
<value>周二/周五/周日</value>
</data>
<data name="ModelBindingCultivationDaysOfWeek36" xml:space="preserve">
<value>周三/周六/周日</value>
</data>
<data name="ModelBindingHutaoComplexAvatarRankFloor" xml:space="preserve">
<value>第 {0} 层</value>
</data>

View File

@@ -187,7 +187,7 @@ internal class CultivationService : ICultivationService
}
return results
.OrderByDescending(e => e.Items.Any(i => i.IsToday))
.OrderByDescending(e => e.IsToday)
.ToObservableCollection();
}
}

View File

@@ -245,8 +245,8 @@ internal class PackageConverter
return false;
}
// Ensure cache folder
string cacheFolder = Path.Combine(gameFolder, "Screenshot", "HutaoCache");
// Cache folder
string cacheFolder = Path.Combine(Core.CoreEnvironment.DataFolder, "ServerCache");
// 执行下载与移动操作
foreach (ItemOperationInfo info in operations)

View File

@@ -90,7 +90,6 @@
<None Remove="View\Dialog\GachaLogUrlDialog.xaml" />
<None Remove="View\Dialog\LaunchGameAccountNameDialog.xaml" />
<None Remove="View\Dialog\LaunchGamePackageConvertDialog.xaml" />
<None Remove="View\Dialog\LoginMihoyoBBSDialog.xaml" />
<None Remove="View\Dialog\SignInWebViewDialog.xaml" />
<None Remove="View\Dialog\UserDialog.xaml" />
<None Remove="View\MainView.xaml" />
@@ -267,11 +266,6 @@
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Page Update="View\Dialog\LoginMihoyoBBSDialog.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Page Update="View\Dialog\DailyNoteNotificationDialog.xaml">
<Generator>MSBuild:Compile</Generator>

View File

@@ -1,31 +0,0 @@
<ContentDialog
x:Class="Snap.Hutao.View.Dialog.LoginMihoyoBBSDialog"
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"
Title="登录到米游社"
CloseButtonText="取消"
DefaultButton="Primary"
PrimaryButtonText="确认"
Style="{StaticResource DefaultContentDialogStyle}"
mc:Ignorable="d">
<Grid>
<StackPanel>
<TextBox
Name="AccountTextBox"
Margin="0,16,0,0"
PlaceholderText="请输入账号"/>
<PasswordBox
Name="PasswordTextBox"
Margin="0,16,0,0"
PlaceholderText="请输入密码"/>
<TextBlock
Margin="0,16,0,0"
Foreground="Yellow"
Text="在此处输入你的米游社账号密码是不安全的,&#10;经过修改的程序可以窃取你的账号信息,&#10;如果担心此方面的问题,请取消登录"/>
</StackPanel>
</Grid>
</ContentDialog>

View File

@@ -1,41 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.
using Microsoft.UI.Xaml.Controls;
using Snap.Hutao.Web.Hoyolab.Passport;
namespace Snap.Hutao.View.Dialog;
/// <summary>
/// 登录到米游社对话框
/// </summary>
public sealed partial class LoginMihoyoBBSDialog : ContentDialog
{
/// <summary>
/// 构造一个新的登录到米游社对话框
/// </summary>
/// <param name="window">窗体</param>
public LoginMihoyoBBSDialog()
{
InitializeComponent();
XamlRoot = Ioc.Default.GetRequiredService<MainWindow>().Content.XamlRoot;
}
/// <summary>
/// 异步获取用户输入的账号密码
/// </summary>
/// <returns>账号密码</returns>
public async Task<ValueResult<bool, Dictionary<string, string>>> GetInputAccountPasswordAsync()
{
await ThreadHelper.SwitchToMainThreadAsync();
bool result = await ShowAsync() == ContentDialogResult.Primary;
Dictionary<string, string> data = new()
{
{ "account", RSAEncryptedString.Encrypt(AccountTextBox.Text) },
{ "password", RSAEncryptedString.Encrypt(PasswordTextBox.Password) },
};
return new(result, data);
}
}

View File

@@ -37,6 +37,12 @@
x:Key="BoolToStyleSelector"
FalseValue="{StaticResource BodyTextBlockStyle}"
TrueValue="{StaticResource BaseTextBlockStyle}"/>
<cwuconv:BoolToObjectConverter x:Key="BoolToBrushSelector" FalseValue="{StaticResource ControlFillColorTransparentBrush}">
<cwuconv:BoolToObjectConverter.TrueValue>
<SolidColorBrush Color="#20A5D610"/>
</cwuconv:BoolToObjectConverter.TrueValue>
</cwuconv:BoolToObjectConverter>
</Page.Resources>
<mxi:Interaction.Behaviors>
@@ -165,7 +171,7 @@
Margin="6,0,0,0"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
Background="Transparent"
Background="{Binding IsToday, Converter={StaticResource BoolToBrushSelector}}"
Command="{Binding Path=DataContext.FinishStateCommand, Source={StaticResource BindingProxy}}"
CommandParameter="{Binding}"
Style="{StaticResource ButtonRevealStyle}">

View File

@@ -2,7 +2,10 @@
// Licensed under the MIT license.
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.WinUI.UI;
using Microsoft.Extensions.DependencyInjection;
using Snap.Hutao.Extension;
using Snap.Hutao.Model;
using Snap.Hutao.Model.Binding.Cultivation;
using Snap.Hutao.Model.Entity;
using Snap.Hutao.Service.Abstraction;
@@ -186,8 +189,6 @@ internal class CultivationViewModel : Abstraction.ViewModel
if (project != null)
{
List<Model.Metadata.Material> materials = await metadataService.GetMaterialsAsync().ConfigureAwait(false);
Dictionary<Model.Primitive.AvatarId, Model.Metadata.Avatar.Avatar> idAvatarMap = await metadataService.GetIdToAvatarMapAsync().ConfigureAwait(false);
Dictionary<Model.Primitive.WeaponId, Model.Metadata.Weapon.Weapon> idWeaponMap = await metadataService.GetIdToWeaponMapAsync().ConfigureAwait(false);
ObservableCollection<Model.Binding.Cultivation.CultivateEntry> entries = await cultivationService
.GetCultivateEntriesAsync(project)

View File

@@ -31,7 +31,6 @@ internal class TestViewModel : Abstraction.ViewModel
ShowCommunityGameRecordDialogCommand = new AsyncRelayCommand(ShowCommunityGameRecordDialogAsync);
ShowAdoptCalculatorDialogCommand = new AsyncRelayCommand(ShowAdoptCalculatorDialogAsync);
DangerousLoginMihoyoBbsCommand = new AsyncRelayCommand(DangerousLoginMihoyoBbsAsync);
DownloadStaticFileCommand = new AsyncRelayCommand(DownloadStaticFileAsync);
}
@@ -45,11 +44,6 @@ internal class TestViewModel : Abstraction.ViewModel
/// </summary>
public ICommand ShowAdoptCalculatorDialogCommand { get; }
/// <summary>
/// Dangerous 登录米游社命令
/// </summary>
public ICommand DangerousLoginMihoyoBbsCommand { get; }
/// <summary>
/// 下载资源文件命令
/// </summary>
@@ -69,38 +63,6 @@ internal class TestViewModel : Abstraction.ViewModel
await new AdoptCalculatorDialog().ShowAsync();
}
private async Task DangerousLoginMihoyoBbsAsync()
{
// ContentDialog must be created by main thread.
await ThreadHelper.SwitchToMainThreadAsync();
(bool isOk, Dictionary<string, string>? data) = await new LoginMihoyoBBSDialog().GetInputAccountPasswordAsync().ConfigureAwait(false);
if (isOk)
{
(Response<LoginResult>? resp, Aigis? aigis) = await serviceProvider
.GetRequiredService<PassportClient2>()
.LoginByPasswordAsync(data, CancellationToken.None)
.ConfigureAwait(false);
if (resp != null)
{
if (resp.IsOk())
{
Cookie cookie = Cookie.FromLoginResult(resp.Data);
await serviceProvider
.GetRequiredService<IUserService>()
.ProcessInputCookieAsync(cookie)
.ConfigureAwait(false);
}
if (resp.ReturnCode == (int)KnownReturnCode.RET_NEED_AIGIS)
{
}
}
}
}
private async Task DownloadStaticFileAsync()
{
BitsManager bitsManager = serviceProvider.GetRequiredService<BitsManager>();

View File

@@ -35,28 +35,6 @@ internal class PassportClient2
this.logger = logger;
}
/// <summary>
/// 异步账密登录
/// </summary>
/// <param name="data">账密数据</param>
/// <param name="token">取消令牌</param>
/// <returns>登录数据</returns>
[ApiInformation(Salt = SaltType.PROD)]
public async Task<ValueResult<Response<LoginResult>?, Aigis?>> LoginByPasswordAsync(Dictionary<string, string> data, CancellationToken token)
{
HttpResponseMessage resp = await httpClient
.UseDynamicSecret(DynamicSecretVersion.Gen2, SaltType.PROD, true)
.PostAsJsonAsync(ApiEndpoints.AccountLoginByPassword, data, options, token)
.ConfigureAwait(false);
_ = resp.Headers.TryGetValues("X-Rpc-Aigis", out IEnumerable<string>? values);
Aigis? aigis = values != null && values.Any() ? JsonSerializer.Deserialize<Aigis>(values.Single(), options) : null;
Response<LoginResult>? body = await resp.Content.ReadFromJsonAsync<Response<LoginResult>>(options, token).ConfigureAwait(false);
return new(body, aigis);
}
/// <summary>
/// V1Stoken 登录
/// </summary>

View File

@@ -1,42 +0,0 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using System.Security.Cryptography;
using System.Text;
namespace Snap.Hutao.Web.Hoyolab.Passport;
/// <summary>
/// 支持RSA转换
/// </summary>
internal class RSAEncryptedString
{
private const string RsaPublicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDvekdPMHN3AYhm/vktJT+YJr7cI5DcsNKqdsx5DZX0gDuWFuIjzdwButrIYPNmRJ1G8ybDIF7oDW2eEpm5sMbL9zs\n9ExXCdvqrn51qELbqj0XxtMTIpaCHFSI50PfPpTFV9Xt/hmyVwokoOXFlAEgCn+Q\nCgGs52bFoYMtyi+xEQIDAQAB\n";
private readonly string encryptedSource;
private RSAEncryptedString(string encryptedSource)
{
this.encryptedSource = encryptedSource;
}
public static implicit operator string(RSAEncryptedString encryptedString)
{
return encryptedString.encryptedSource;
}
/// <summary>
/// 加密
/// </summary>
/// <param name="source">源</param>
/// <returns>字节数组</returns>
public static RSAEncryptedString Encrypt(string source)
{
RSA rsa = RSA.Create();
rsa.ImportFromPem($"-----BEGIN PUBLIC KEY-----\n{RsaPublicKey}-----END PUBLIC KEY-----");
byte[] bytes = Encoding.UTF8.GetBytes(source);
string encrypted = Convert.ToBase64String(rsa.Encrypt(bytes, RSAEncryptionPadding.Pkcs1));
return new(encrypted);
}
}