mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
fix avatarInfo def value
This commit is contained in:
6
desktop.ini
Normal file
6
desktop.ini
Normal file
@@ -0,0 +1,6 @@
|
||||
[.ShellClassInfo]
|
||||
IconResource=D:\Develop\Projects\Snap.Hutao\src\Snap.Hutao\Snap.Hutao\Assets\Logo.ico,0
|
||||
[ViewState]
|
||||
Mode=
|
||||
Vid=
|
||||
FolderType=Generic
|
||||
@@ -23,6 +23,13 @@ internal class JsonTextEncoder : JavaScriptEncoder
|
||||
/// <inheritdoc/>
|
||||
public override unsafe bool TryEncodeUnicodeScalar(int unicodeScalar, char* buffer, int bufferLength, out int numberOfCharactersWritten)
|
||||
{
|
||||
// " => \"
|
||||
if (unicodeScalar == '"')
|
||||
{
|
||||
numberOfCharactersWritten = 2;
|
||||
return "\\\"".AsSpan().TryCopyTo(new Span<char>(buffer, bufferLength));
|
||||
}
|
||||
|
||||
string encoded = $"\\u{(uint)unicodeScalar:x4}";
|
||||
numberOfCharactersWritten = (encoded.Length <= (uint)bufferLength) ? encoded.Length : 0;
|
||||
return encoded.AsSpan().TryCopyTo(new Span<char>(buffer, bufferLength));
|
||||
@@ -31,6 +38,6 @@ internal class JsonTextEncoder : JavaScriptEncoder
|
||||
/// <inheritdoc/>
|
||||
public override bool WillEncode(int unicodeScalar)
|
||||
{
|
||||
return true;
|
||||
return unicodeScalar == '=';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,12 +41,12 @@ public class User : ObservableObject
|
||||
public List<UserGameRole> UserGameRoles { get; private set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 用户信息
|
||||
/// 用户信息, 请勿访问set
|
||||
/// </summary>
|
||||
public UserGameRole? SelectedUserGameRole
|
||||
{
|
||||
get => selectedUserGameRole;
|
||||
private set => SetProperty(ref selectedUserGameRole, value);
|
||||
set => SetProperty(ref selectedUserGameRole, value);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="EntityUser.IsSelected"/>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<Identity
|
||||
Name="7f0db578-026f-4e0b-a75b-d5d06bb0a74d"
|
||||
Publisher="CN=DGP Studio"
|
||||
Version="1.2.0.0" />
|
||||
Version="1.2.2.0" />
|
||||
|
||||
<Properties>
|
||||
<DisplayName>胡桃</DisplayName>
|
||||
|
||||
@@ -118,7 +118,7 @@ internal static class SummaryHelper
|
||||
double def = fightPropMap.GetValueOrDefault2(FightProperty.FIGHT_PROP_DEFENSE); // 8
|
||||
double defPercent = fightPropMap.GetValueOrDefault2(FightProperty.FIGHT_PROP_DEFENSE_PERCENT); // 9
|
||||
double defAdd = def + (baseDef * defPercent);
|
||||
double maxDef = baseDef + defPercent;
|
||||
double maxDef = baseDef + defAdd;
|
||||
Pair2<string, string, string?> defPair2 = PropertyInfoDescriptor.FormatIntegerPair2("防御力", FormatMethod.Integer, maxDef, defAdd);
|
||||
|
||||
double em = fightPropMap.GetValueOrDefault2(FightProperty.FIGHT_PROP_ELEMENT_MASTERY); // 28
|
||||
|
||||
@@ -90,7 +90,7 @@ internal class UserService : IUserService
|
||||
|
||||
// Sync cache
|
||||
userCollection!.Remove(user);
|
||||
roleCollection!.RemoveWhere(r => r.User.InnerId == user.Entity.InnerId);
|
||||
roleCollection?.RemoveWhere(r => r.User.InnerId == user.Entity.InnerId);
|
||||
|
||||
// Sync database
|
||||
using (IServiceScope scope = scopeFactory.CreateScope())
|
||||
@@ -191,8 +191,7 @@ internal class UserService : IUserService
|
||||
{
|
||||
AppDbContext appDbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
|
||||
// 检查 stoken 是否存在
|
||||
if (user.HasStoken)
|
||||
if (cookie.IsStoken())
|
||||
{
|
||||
// update stoken
|
||||
await ThreadHelper.SwitchToMainThreadAsync();
|
||||
@@ -201,14 +200,15 @@ internal class UserService : IUserService
|
||||
|
||||
return new(UserOptionResult.Upgraded, mid);
|
||||
}
|
||||
|
||||
await ThreadHelper.SwitchToMainThreadAsync();
|
||||
else
|
||||
{
|
||||
user.Cookie = cookie;
|
||||
appDbContext.Users.UpdateAndSave(user.Entity);
|
||||
|
||||
return new(UserOptionResult.Updated, mid);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return await TryCreateUserAndAddAsync(cookie).ConfigureAwait(false);
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<AppxPackageSigningEnabled>True</AppxPackageSigningEnabled>
|
||||
<PackageCertificateThumbprint>F8C2255969BEA4A681CED102771BF807856AEC02</PackageCertificateThumbprint>
|
||||
<AppxPackageSigningTimestampDigestAlgorithm>SHA256</AppxPackageSigningTimestampDigestAlgorithm>
|
||||
<AppxAutoIncrementPackageRevision>False</AppxAutoIncrementPackageRevision>
|
||||
<AppxAutoIncrementPackageRevision>True</AppxAutoIncrementPackageRevision>
|
||||
<AppxSymbolPackageEnabled>True</AppxSymbolPackageEnabled>
|
||||
<GenerateTestArtifacts>True</GenerateTestArtifacts>
|
||||
<AppxBundle>Never</AppxBundle>
|
||||
|
||||
@@ -16,7 +16,7 @@ public sealed partial class LoginMihoyoBBSDialog : ContentDialog
|
||||
/// <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>µĵ<C2B5>¼<EFBFBD><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ի<EFBFBD><D4BB><EFBFBD>
|
||||
/// </summary>
|
||||
/// <param name="window"><3E><><EFBFBD><EFBFBD></param>
|
||||
public LoginMihoyoBBSDialog(Window window)
|
||||
public LoginMihoyoBBSDialog(MainWindow window)
|
||||
{
|
||||
InitializeComponent();
|
||||
XamlRoot = window.Content.XamlRoot;
|
||||
|
||||
@@ -206,8 +206,8 @@
|
||||
Height="40"
|
||||
Width="40"
|
||||
Background="{StaticResource CardBackgroundFillColorDefaultBrush}"
|
||||
Value="{Binding DailyNote.CurrentResin,Mode=OneWay}"
|
||||
Maximum="{Binding DailyNote.MaxResin,Mode=OneWay}"
|
||||
Value="{Binding DailyNote.CurrentResin,Mode=OneWay}"
|
||||
IsIndeterminate="False"/>
|
||||
</Grid>
|
||||
<TextBlock
|
||||
@@ -288,8 +288,8 @@
|
||||
Height="40"
|
||||
Width="40"
|
||||
Background="{StaticResource CardBackgroundFillColorDefaultBrush}"
|
||||
Value="{Binding DailyNote.FinishedTaskNum,Mode=OneWay}"
|
||||
Maximum="{Binding DailyNote.TotalTaskNum,Mode=OneWay}"
|
||||
Value="{Binding DailyNote.FinishedTaskNum,Mode=OneWay}"
|
||||
IsIndeterminate="False"/>
|
||||
</Grid>
|
||||
<TextBlock
|
||||
@@ -329,8 +329,8 @@
|
||||
Height="40"
|
||||
Width="40"
|
||||
Background="{StaticResource CardBackgroundFillColorDefaultBrush}"
|
||||
Value="{Binding DailyNote.ResinDiscountUsedNum,Mode=OneWay}"
|
||||
Maximum="{Binding DailyNote.ResinDiscountNumLimit,Mode=OneWay}"
|
||||
Value="{Binding DailyNote.ResinDiscountUsedNum,Mode=OneWay}"
|
||||
IsIndeterminate="False"/>
|
||||
</Grid>
|
||||
<TextBlock
|
||||
@@ -370,8 +370,8 @@
|
||||
Height="40"
|
||||
Width="40"
|
||||
Background="{StaticResource CardBackgroundFillColorDefaultBrush}"
|
||||
Value="{Binding DailyNote.Transformer.RecoveryTime.TotalSeconds,Mode=OneWay}"
|
||||
Maximum="604800"
|
||||
Value="{Binding DailyNote.Transformer.RecoveryTime.TotalSeconds,Mode=OneWay}"
|
||||
IsIndeterminate="False"/>
|
||||
</Grid>
|
||||
<TextBlock
|
||||
|
||||
@@ -100,7 +100,18 @@ internal class DailyNoteViewModel : ObservableObject, ISupportCancellation
|
||||
/// <summary>
|
||||
/// 提醒式通知
|
||||
/// </summary>
|
||||
public bool IsReminderNotification { get => isReminderNotification; set => SetProperty(ref isReminderNotification, value); }
|
||||
public bool IsReminderNotification
|
||||
{
|
||||
get => isReminderNotification;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref isReminderNotification, value))
|
||||
{
|
||||
reminderNotifyEntry.SetBoolean(value);
|
||||
appDbContext.Settings.UpdateAndSave(reminderNotifyEntry!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用户与角色集合
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Snap.Hutao.Context.Database;
|
||||
using Snap.Hutao.Core.Database;
|
||||
using Snap.Hutao.Core.Windowing;
|
||||
@@ -12,7 +12,11 @@ using Snap.Hutao.Model;
|
||||
using Snap.Hutao.Model.Entity;
|
||||
using Snap.Hutao.Service.Game;
|
||||
using Snap.Hutao.Service.Game.Locator;
|
||||
using Snap.Hutao.Service.User;
|
||||
using Snap.Hutao.View.Dialog;
|
||||
using Snap.Hutao.Web.Hoyolab;
|
||||
using Snap.Hutao.Web.Hoyolab.Passport;
|
||||
using Snap.Hutao.Web.Response;
|
||||
|
||||
namespace Snap.Hutao.ViewModel;
|
||||
|
||||
@@ -44,7 +48,11 @@ internal class SettingViewModel : ObservableObject
|
||||
/// <param name="gameService">游戏服务</param>
|
||||
/// <param name="asyncRelayCommandFactory">异步命令工厂</param>
|
||||
/// <param name="experimental">实验性功能</param>
|
||||
public SettingViewModel(AppDbContext appDbContext, IGameService gameService, IAsyncRelayCommandFactory asyncRelayCommandFactory, ExperimentalFeaturesViewModel experimental)
|
||||
public SettingViewModel(
|
||||
AppDbContext appDbContext,
|
||||
IGameService gameService,
|
||||
IAsyncRelayCommandFactory asyncRelayCommandFactory,
|
||||
ExperimentalFeaturesViewModel experimental)
|
||||
{
|
||||
this.appDbContext = appDbContext;
|
||||
this.gameService = gameService;
|
||||
@@ -64,7 +72,7 @@ internal class SettingViewModel : ObservableObject
|
||||
GamePath = gameService.GetGamePathSkipLocator();
|
||||
|
||||
SetGamePathCommand = asyncRelayCommandFactory.Create(SetGamePathAsync);
|
||||
DebugExceptionCommand = new RelayCommand(DebugThrowException);
|
||||
DebugExceptionCommand = asyncRelayCommandFactory.Create(DebugThrowExceptionAsync);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -154,13 +162,35 @@ internal class SettingViewModel : ObservableObject
|
||||
}
|
||||
}
|
||||
|
||||
private async void DebugThrowException()
|
||||
private async Task DebugThrowExceptionAsync()
|
||||
{
|
||||
#if DEBUG
|
||||
PassportClient2 passportClient2 = Ioc.Default.GetRequiredService<PassportClient2>();
|
||||
LoginResult? data = await passportClient2.LoginByPasswordAsync("phoneNunmber", "password", CancellationToken.None).ConfigureAwait(false);
|
||||
LoginMihoyoBBSDialog dialog = ActivatorUtilities.CreateInstance<LoginMihoyoBBSDialog>(Ioc.Default);
|
||||
(bool isOk, Dictionary<string, string>? data) = await dialog.GetInputAccountPasswordAsync().ConfigureAwait(false);
|
||||
|
||||
_ = data;
|
||||
if (isOk)
|
||||
{
|
||||
(Response<LoginResult>? resp, Aigis? aigis) = await Ioc.Default
|
||||
.GetRequiredService<PassportClient2>()
|
||||
.LoginByPasswordAsync(data, CancellationToken.None)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (resp != null)
|
||||
{
|
||||
if (resp.IsOk())
|
||||
{
|
||||
Cookie cookie = Cookie.FromLoginResult(resp.Data!);
|
||||
await Ioc.Default
|
||||
.GetRequiredService<IUserService>()
|
||||
.ProcessInputCookieAsync(cookie)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (resp.ReturnCode == (int)KnownReturnCode.RET_NEED_AIGIS)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,30 @@ namespace Snap.Hutao.Web.Hoyolab;
|
||||
[SuppressMessage("", "SA1124")]
|
||||
internal static class ApiEndpoints
|
||||
{
|
||||
#region
|
||||
|
||||
/// <summary>
|
||||
/// 获取GT码
|
||||
/// </summary>
|
||||
/// <param name="gt">gt</param>
|
||||
/// <returns>GT码Url</returns>
|
||||
public static string GeetestGetType(string gt)
|
||||
{
|
||||
return $"{ApiGeetest}/gettype.php?gt={gt}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证接口
|
||||
/// </summary>
|
||||
/// <param name="gt">gt</param>
|
||||
/// <param name="challenge">challenge流水号</param>
|
||||
/// <returns>验证接口Url</returns>
|
||||
public static string GeetestAjax(string gt, string challenge)
|
||||
{
|
||||
return $"{ApiV6Geetest}/ajax.php?gt={gt}&challenge={challenge}&lang=zh-cn&pt=3&client_type=web_mobile";
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ApiTakumiAuthApi
|
||||
|
||||
/// <summary>
|
||||
@@ -217,6 +241,9 @@ internal static class ApiEndpoints
|
||||
#endregion
|
||||
|
||||
// consts
|
||||
private const string ApiGeetest = "https://api.geetest.com";
|
||||
private const string ApiV6Geetest = "https://apiv6.geetest.com";
|
||||
|
||||
private const string ApiTakumi = "https://api-takumi.mihoyo.com";
|
||||
private const string ApiTakumiAuthApi = $"{ApiTakumi}/auth/api";
|
||||
private const string ApiTaKumiBindingApi = $"{ApiTakumi}/binding/api";
|
||||
|
||||
@@ -42,7 +42,7 @@ internal class UserClient
|
||||
{
|
||||
Response<UserFullInfoWrapper>? resp = await httpClient
|
||||
.SetUser(user, CookieType.Cookie)
|
||||
.SetReferer(ApiEndpoints.BbsReferer)
|
||||
.SetReferer(ApiEndpoints.BbsReferer) // Otherwise HTTP 403
|
||||
.TryCatchGetFromJsonAsync<Response<UserFullInfoWrapper>>(ApiEndpoints.UserFullInfo, options, logger, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ internal class UserClient2
|
||||
{
|
||||
Response<UserFullInfoWrapper>? resp = await httpClient
|
||||
.SetUser(user, CookieType.Stoken)
|
||||
//.SetReferer(ApiEndpoints.BbsReferer)
|
||||
.SetReferer(ApiEndpoints.BbsReferer)
|
||||
.UseDynamicSecret(DynamicSecretVersion.Gen1, SaltType.K2, true)
|
||||
.TryCatchGetFromJsonAsync<Response<UserFullInfoWrapper>>(ApiEndpoints.UserFullInfoQuery(uid), options, logger, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
@@ -65,6 +65,23 @@ public partial class Cookie
|
||||
return new(cookieMap);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从登录结果创建Cookie
|
||||
/// </summary>
|
||||
/// <param name="loginResult">登录结果</param>
|
||||
/// <returns>Cookie</returns>
|
||||
public static Cookie FromLoginResult(LoginResult loginResult)
|
||||
{
|
||||
SortedDictionary<string, string> cookieMap = new()
|
||||
{
|
||||
[STUID] = loginResult.UserInfo.Aid,
|
||||
[STOKEN] = loginResult.Token.Token,
|
||||
[MID] = loginResult.UserInfo.Mid,
|
||||
};
|
||||
|
||||
return new(cookieMap);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 此 Cookie 是 SToken
|
||||
/// </summary>
|
||||
|
||||
@@ -14,7 +14,7 @@ public enum CookieType
|
||||
None,
|
||||
|
||||
/// <summary>
|
||||
/// 需要 Ltoken & CookieToken & e_hk4e_token
|
||||
/// 需要 Ltoken & CookieToken
|
||||
/// </summary>
|
||||
Cookie,
|
||||
|
||||
@@ -22,9 +22,4 @@ public enum CookieType
|
||||
/// 需要 Stoken
|
||||
/// </summary>
|
||||
Stoken,
|
||||
|
||||
/// <summary>
|
||||
/// 全部
|
||||
/// </summary>
|
||||
All,
|
||||
}
|
||||
@@ -5,6 +5,7 @@ using Snap.Hutao.Core.Convert;
|
||||
using Snap.Hutao.Web.Request;
|
||||
using System.Collections.Immutable;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Json;
|
||||
using System.Text;
|
||||
|
||||
namespace Snap.Hutao.Web.Hoyolab.DynamicSecret;
|
||||
@@ -28,26 +29,28 @@ public class DynamicSecretHandler : DelegatingHandler
|
||||
}.ToImmutableDictionary();
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken token)
|
||||
{
|
||||
if (request.Headers.TryGetValues("DS-Option", out IEnumerable<string>? values))
|
||||
{
|
||||
string[] definations = values.Single().Split('|');
|
||||
string version = definations[0];
|
||||
string saltType = definations[1];
|
||||
bool includeCharsKey = definations[2] == "true";
|
||||
bool includeChars = definations[2] == "true";
|
||||
|
||||
string salt = DynamicSecrets[saltType];
|
||||
|
||||
long t = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||
|
||||
string r = includeCharsKey ? GetRandomStringWithChars() : GetRandomStringNoChars();
|
||||
string r = includeChars ? GetRandomStringWithChars() : GetRandomStringNoChars();
|
||||
|
||||
string dsContent = $"salt={salt}&t={t}&r={r}";
|
||||
|
||||
if (version == nameof(DynamicSecretVersion.Gen2))
|
||||
{
|
||||
string b = request.Content?.ToString() ?? (saltType == nameof(SaltType.PROD) ? "{}" : string.Empty);
|
||||
string b = request.Content != null
|
||||
? await request.Content.ReadAsStringAsync(token).ConfigureAwait(false)
|
||||
: (saltType == nameof(SaltType.PROD) ? "{}" : string.Empty);
|
||||
|
||||
string[] queries = Uri.UnescapeDataString(request.RequestUri!.Query).Split('?', 2);
|
||||
string q = queries.Length == 2 ? string.Join('&', queries[1].Split('&').OrderBy(x => x)) : string.Empty;
|
||||
@@ -61,7 +64,7 @@ public class DynamicSecretHandler : DelegatingHandler
|
||||
request.Headers.Set("DS", $"{t},{r},{check}");
|
||||
}
|
||||
|
||||
return base.SendAsync(request, cancellationToken);
|
||||
return await base.SendAsync(request, token).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static string GetRandomStringWithChars()
|
||||
|
||||
28
src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/Aigis.cs
Normal file
28
src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/Passport/Aigis.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Web.Hoyolab.Passport;
|
||||
|
||||
/// <summary>
|
||||
/// 极验
|
||||
/// </summary>
|
||||
public class Aigis
|
||||
{
|
||||
/// <summary>
|
||||
/// 极验会话Id
|
||||
/// </summary>
|
||||
[JsonPropertyName("session_id")]
|
||||
public string SessionId { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 验证类型 1
|
||||
/// </summary>
|
||||
[JsonPropertyName("mmt_type")]
|
||||
public int MmtType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数据
|
||||
/// </summary>
|
||||
[JsonPropertyName("data")]
|
||||
public string Data { get; set; } = default!;
|
||||
}
|
||||
@@ -7,12 +7,14 @@ using Snap.Hutao.Web.Hoyolab.Annotation;
|
||||
using Snap.Hutao.Web.Hoyolab.DynamicSecret;
|
||||
using Snap.Hutao.Web.Response;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Json;
|
||||
|
||||
namespace Snap.Hutao.Web.Hoyolab.Passport;
|
||||
|
||||
/// <summary>
|
||||
/// 通行证客户端 XRPC 版
|
||||
/// </summary>
|
||||
[UseDynamicSecret]
|
||||
[HttpClient(HttpClientConfigration.XRpc2)]
|
||||
internal class PassportClient2
|
||||
{
|
||||
@@ -36,25 +38,23 @@ internal class PassportClient2
|
||||
/// <summary>
|
||||
/// 异步账密登录
|
||||
/// </summary>
|
||||
/// <param name="account">用户</param>
|
||||
/// <param name="password">密码</param>
|
||||
/// <param name="data">账密数据</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>登录数据</returns>
|
||||
[ApiInformation(Salt = SaltType.PROD)]
|
||||
public async Task<LoginResult?> LoginByPasswordAsync(string account, string password, CancellationToken token)
|
||||
public async Task<ValueResult<Response<LoginResult>?, Aigis?>> LoginByPasswordAsync(Dictionary<string, string> data, CancellationToken token)
|
||||
{
|
||||
Dictionary<string, string> data = new()
|
||||
{
|
||||
{ "account", RSAEncryptedString.Encrypt(account) },
|
||||
{ "password", RSAEncryptedString.Encrypt(password) },
|
||||
};
|
||||
|
||||
Response<LoginResult>? resp = await httpClient
|
||||
HttpResponseMessage resp = await httpClient
|
||||
.UseDynamicSecret(DynamicSecretVersion.Gen2, SaltType.PROD, true)
|
||||
.TryCatchPostAsJsonAsync<Dictionary<string, string>, Response<LoginResult>>(ApiEndpoints.AccountLoginByPassword, data, options, logger, token)
|
||||
.PostAsJsonAsync(ApiEndpoints.AccountLoginByPassword, data, options, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return resp?.Data;
|
||||
_ = 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>
|
||||
|
||||
@@ -61,13 +61,13 @@ internal class BindingClient2
|
||||
/// <param name="data">提交数据</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>用户角色信息</returns>
|
||||
[ApiInformation(Cookie = CookieType.Stoken, Salt = SaltType.K2)]
|
||||
[ApiInformation(Cookie = CookieType.Stoken, Salt = SaltType.LK2)]
|
||||
public async Task<GameAuthKey?> GenerateAuthenticationKeyAsync(User user, GenAuthKeyData data, CancellationToken token = default)
|
||||
{
|
||||
Response<GameAuthKey>? resp = await httpClient
|
||||
.SetUser(user, CookieType.Stoken)
|
||||
.SetReferer("https://app.mihoyo.com")
|
||||
.UseDynamicSecret(DynamicSecretVersion.Gen1, SaltType.K2, true)
|
||||
.UseDynamicSecret(DynamicSecretVersion.Gen1, SaltType.LK2, true)
|
||||
.TryCatchPostAsJsonAsync<GenAuthKeyData, Response<GameAuthKey>>(ApiEndpoints.BindingGenAuthKey, data, options, logger, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
|
||||
@@ -119,12 +119,13 @@ internal class GameRecordClient
|
||||
/// </summary>
|
||||
/// <param name="user">用户</param>
|
||||
/// <param name="uid">uid</param>
|
||||
/// <param name="playerInfo">玩家的基础信息</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>角色列表</returns>
|
||||
[ApiInformation(Cookie = CookieType.Cookie, Salt = SaltType.X4)]
|
||||
public async Task<List<Character>> GetCharactersAsync(User user, PlayerUid uid, CancellationToken token = default)
|
||||
public async Task<List<Character>> GetCharactersAsync(User user, PlayerUid uid, PlayerInfo playerInfo, CancellationToken token = default)
|
||||
{
|
||||
CharacterData data = new(uid);
|
||||
CharacterData data = new(uid, playerInfo.Avatars.Select(x => x.Id));
|
||||
|
||||
Response<CharacterWrapper>? resp = await httpClient
|
||||
.SetUser(user, CookieType.Cookie)
|
||||
@@ -155,12 +156,16 @@ internal class GameRecordClient
|
||||
|
||||
private class CharacterData
|
||||
{
|
||||
public CharacterData(PlayerUid uid)
|
||||
public CharacterData(PlayerUid uid, IEnumerable<int> characterIds)
|
||||
{
|
||||
CharacterIds = characterIds;
|
||||
Uid = uid.Value;
|
||||
Server = uid.Region;
|
||||
}
|
||||
|
||||
[JsonPropertyName("character_ids")]
|
||||
public IEnumerable<int> CharacterIds { get; }
|
||||
|
||||
[JsonPropertyName("role_id")]
|
||||
public string Uid { get; }
|
||||
|
||||
|
||||
@@ -177,8 +177,13 @@ internal class HomaClient
|
||||
{
|
||||
Must.NotNull(user.SelectedUserGameRole!);
|
||||
|
||||
PlayerInfo? playerInfo = await gameRecordClient
|
||||
.GetPlayerInfoAsync(user.Entity, user.SelectedUserGameRole, token)
|
||||
.ConfigureAwait(false);
|
||||
Must.NotNull(playerInfo!);
|
||||
|
||||
List<Character> characters = await gameRecordClient
|
||||
.GetCharactersAsync(user.Entity, user.SelectedUserGameRole, token)
|
||||
.GetCharactersAsync(user.Entity, user.SelectedUserGameRole, playerInfo, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
SpiralAbyss? spiralAbyssInfo = await gameRecordClient
|
||||
|
||||
@@ -19,7 +19,7 @@ public enum KnownReturnCode : int
|
||||
AlreadySignedIn = -5003,
|
||||
|
||||
/// <summary>
|
||||
/// 需要风险验证
|
||||
/// 需要风险验证(闪验)
|
||||
/// </summary>
|
||||
RET_NEED_RISK_VERIFY = -3235,
|
||||
|
||||
@@ -88,8 +88,18 @@ public enum KnownReturnCode : int
|
||||
/// </summary>
|
||||
CODE1034 = 1034,
|
||||
|
||||
/// <summary>
|
||||
/// 请登录
|
||||
/// </summary>
|
||||
PleaseLogin = 10001,
|
||||
|
||||
/// <summary>
|
||||
/// 数据未公开
|
||||
/// </summary>
|
||||
DataIsNotPublicForTheUser = 10102,
|
||||
|
||||
/// <summary>
|
||||
/// 实时便笺
|
||||
/// </summary>
|
||||
CODE10104 = 10104,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user