mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
remove DS1
This commit is contained in:
@@ -41,7 +41,7 @@ internal struct ValueStopwatch
|
||||
/// </summary>
|
||||
/// <returns>经过的时间</returns>
|
||||
/// <exception cref="InvalidOperationException">当前的停表未合理的初始化</exception>
|
||||
public TimeSpan GetElapsedTime()
|
||||
public long GetElapsedTimestamp()
|
||||
{
|
||||
// Start timestamp can't be zero in an initialized ValueStopwatch.
|
||||
// It would have to be literally the first thing executed when the machine boots to be 0.
|
||||
@@ -52,6 +52,16 @@ internal struct ValueStopwatch
|
||||
long timestampDelta = end - startTimestamp;
|
||||
long ticks = (long)(TimestampToTicks * timestampDelta);
|
||||
|
||||
return new TimeSpan(ticks);
|
||||
return ticks;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取经过的时间
|
||||
/// </summary>
|
||||
/// <returns>经过的时间</returns>
|
||||
/// <exception cref="InvalidOperationException">当前的停表未合理的初始化</exception>
|
||||
public TimeSpan GetElapsedTime()
|
||||
{
|
||||
return new TimeSpan(GetElapsedTimestamp());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,7 @@ namespace Snap.Hutao.Core.Logging;
|
||||
internal sealed partial class DatebaseLogger : ILogger
|
||||
{
|
||||
private readonly string name;
|
||||
private readonly LogDbContext logDbContext;
|
||||
private readonly object logDbContextLock;
|
||||
private readonly LogEntryQueue logEntryQueue;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DatebaseLogger"/> class.
|
||||
@@ -20,11 +19,10 @@ internal sealed partial class DatebaseLogger : ILogger
|
||||
/// <param name="name">The name of the logger.</param>
|
||||
/// <param name="logDbContext">应用程序数据库上下文</param>
|
||||
/// <param name="logDbContextLock">上下文锁</param>
|
||||
public DatebaseLogger(string name, LogDbContext logDbContext, object logDbContextLock)
|
||||
public DatebaseLogger(string name, LogEntryQueue logEntryQueue)
|
||||
{
|
||||
this.name = name;
|
||||
this.logDbContext = logDbContext;
|
||||
this.logDbContextLock = logDbContextLock;
|
||||
this.logEntryQueue = logEntryQueue;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -47,7 +45,7 @@ internal sealed partial class DatebaseLogger : ILogger
|
||||
return;
|
||||
}
|
||||
|
||||
string message = Must.NotNull(formatter)(state, exception);
|
||||
string message = formatter(state, exception);
|
||||
|
||||
if (string.IsNullOrEmpty(message))
|
||||
{
|
||||
@@ -63,12 +61,7 @@ internal sealed partial class DatebaseLogger : ILogger
|
||||
Exception = exception?.ToString(),
|
||||
};
|
||||
|
||||
// DbContext is not a thread safe class, so we have to lock the wirte procedure
|
||||
lock (logDbContextLock)
|
||||
{
|
||||
logDbContext.Logs.Add(entry);
|
||||
logDbContext.SaveChanges();
|
||||
}
|
||||
logEntryQueue.Enqueue(entry);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Snap.Hutao.Context.Database;
|
||||
using Snap.Hutao.Context.FileSystem;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
||||
namespace Snap.Hutao.Core.Logging;
|
||||
|
||||
/// <summary>
|
||||
@@ -15,49 +9,17 @@ namespace Snap.Hutao.Core.Logging;
|
||||
[ProviderAlias("Database")]
|
||||
public sealed class DatebaseLoggerProvider : ILoggerProvider
|
||||
{
|
||||
private static readonly object LogDbContextLock = new();
|
||||
|
||||
// the provider is created per logger, we don't want to create too much
|
||||
private static volatile LogDbContext? logDbContext;
|
||||
|
||||
private static LogDbContext LogDbContext
|
||||
{
|
||||
get
|
||||
{
|
||||
if (logDbContext == null)
|
||||
{
|
||||
lock (LogDbContextLock)
|
||||
{
|
||||
// prevent re-entry call
|
||||
if (logDbContext == null)
|
||||
{
|
||||
HutaoContext myDocument = new(new());
|
||||
logDbContext = LogDbContext.Create($"Data Source={myDocument.Locate("Log.db")}");
|
||||
if (logDbContext.Database.GetPendingMigrations().Any())
|
||||
{
|
||||
Debug.WriteLine("[Debug] Performing LogDbContext Migrations");
|
||||
logDbContext.Database.Migrate();
|
||||
}
|
||||
|
||||
logDbContext.Logs.RemoveRange(logDbContext.Logs);
|
||||
logDbContext.SaveChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return logDbContext;
|
||||
}
|
||||
}
|
||||
private readonly LogEntryQueue logEntryQueue = new();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ILogger CreateLogger(string name)
|
||||
{
|
||||
return new DatebaseLogger(name, LogDbContext, LogDbContextLock);
|
||||
return new DatebaseLogger(name, logEntryQueue);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
LogDbContext.Dispose();
|
||||
logEntryQueue.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
119
src/Snap.Hutao/Snap.Hutao/Core/Logging/LogEntryQueue.cs
Normal file
119
src/Snap.Hutao/Snap.Hutao/Core/Logging/LogEntryQueue.cs
Normal file
@@ -0,0 +1,119 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Snap.Hutao.Context.Database;
|
||||
using Snap.Hutao.Context.FileSystem;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
||||
namespace Snap.Hutao.Core.Logging;
|
||||
|
||||
/// <summary>
|
||||
/// 日志队列
|
||||
/// </summary>
|
||||
public sealed class LogEntryQueue : IDisposable
|
||||
{
|
||||
private static readonly object LogDbContextCreationLock = new();
|
||||
|
||||
private readonly ConcurrentQueue<LogEntry> entryQueue = new();
|
||||
private readonly CancellationTokenSource disposeCancellationTokenSource = new();
|
||||
private readonly TaskCompletionSource writeDbTaskCompletionSource = new();
|
||||
|
||||
// the provider is created per logger, we don't want to create too much
|
||||
private volatile LogDbContext? logDbContext;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的日志队列
|
||||
/// </summary>
|
||||
public LogEntryQueue()
|
||||
{
|
||||
Execute();
|
||||
}
|
||||
|
||||
private LogDbContext LogDbContext
|
||||
{
|
||||
get
|
||||
{
|
||||
if (logDbContext == null)
|
||||
{
|
||||
lock (LogDbContextCreationLock)
|
||||
{
|
||||
// prevent re-entry call
|
||||
if (logDbContext == null)
|
||||
{
|
||||
HutaoContext myDocument = new(new());
|
||||
logDbContext = LogDbContext.Create($"Data Source={myDocument.Locate("Log.db")}");
|
||||
if (logDbContext.Database.GetPendingMigrations().Any())
|
||||
{
|
||||
Debug.WriteLine("[Debug] Performing LogDbContext Migrations");
|
||||
logDbContext.Database.Migrate();
|
||||
}
|
||||
|
||||
logDbContext.Logs.RemoveRange(logDbContext.Logs);
|
||||
logDbContext.SaveChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return logDbContext;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将日志消息存入队列
|
||||
/// </summary>
|
||||
/// <param name="logEntry">日志</param>
|
||||
public void Enqueue(LogEntry logEntry)
|
||||
{
|
||||
entryQueue.Enqueue(logEntry);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
[SuppressMessage("", "VSTHRD002")]
|
||||
public void Dispose()
|
||||
{
|
||||
disposeCancellationTokenSource.Cancel();
|
||||
writeDbTaskCompletionSource.Task.GetAwaiter().GetResult();
|
||||
|
||||
LogDbContext.Dispose();
|
||||
}
|
||||
|
||||
[SuppressMessage("", "VSTHRD100")]
|
||||
private async void Execute()
|
||||
{
|
||||
await Task.Run(async () => await ExecuteCoreAsync(disposeCancellationTokenSource.Token));
|
||||
}
|
||||
|
||||
private async Task ExecuteCoreAsync(CancellationToken token)
|
||||
{
|
||||
bool hasAdded = false;
|
||||
while (true)
|
||||
{
|
||||
if (entryQueue.TryDequeue(out LogEntry? logEntry))
|
||||
{
|
||||
LogDbContext.Logs.Add(logEntry);
|
||||
hasAdded = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hasAdded)
|
||||
{
|
||||
LogDbContext.SaveChanges();
|
||||
hasAdded = false;
|
||||
}
|
||||
|
||||
if (token.IsCancellationRequested)
|
||||
{
|
||||
writeDbTaskCompletionSource.TrySetResult();
|
||||
break;
|
||||
}
|
||||
|
||||
await Task
|
||||
.Delay(1000, CancellationToken.None)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using System.Diagnostics;
|
||||
using Windows.Win32.Foundation;
|
||||
using Windows.Win32.UI.Shell;
|
||||
using static Windows.Win32.PInvoke;
|
||||
|
||||
@@ -42,9 +42,5 @@ public sealed partial class MainWindow : Window
|
||||
messenger.Send(new MainWindowClosedMessage());
|
||||
|
||||
windowManager?.Dispose();
|
||||
|
||||
// save userdata datebase
|
||||
int changes = appDbContext.SaveChanges();
|
||||
Verify.Operation(changes == 0, "存在未经处理的数据库记录更改");
|
||||
}
|
||||
}
|
||||
@@ -39,11 +39,13 @@ public static class Program
|
||||
XamlCheckProcessRequirements();
|
||||
ComWrappersSupport.InitializeComWrappers();
|
||||
|
||||
InitializeDependencyInjection();
|
||||
|
||||
// In a Desktop app this runs a message pump internally,
|
||||
// and does not return until the application shuts down.
|
||||
Application.Start(InitializeApp);
|
||||
// by adding the using statement, we can dispose the injected services when we closing
|
||||
using (InitializeDependencyInjection())
|
||||
{
|
||||
// In a Desktop app this runs a message pump internally,
|
||||
// and does not return until the application shuts down.
|
||||
Application.Start(InitializeApp);
|
||||
}
|
||||
}
|
||||
|
||||
private static void InitializeApp(ApplicationInitializationCallbackParams param)
|
||||
@@ -55,9 +57,13 @@ public static class Program
|
||||
_ = Ioc.Default.GetRequiredService<App>();
|
||||
}
|
||||
|
||||
private static void InitializeDependencyInjection()
|
||||
/// <summary>
|
||||
/// 初始化依赖注入
|
||||
/// </summary>
|
||||
/// <returns>The ServiceProvider, so that we can dispose it.</returns>
|
||||
private static ServiceProvider InitializeDependencyInjection()
|
||||
{
|
||||
IServiceProvider services = new ServiceCollection()
|
||||
ServiceProvider services = new ServiceCollection()
|
||||
|
||||
// Microsoft extension
|
||||
.AddLogging(builder => builder
|
||||
@@ -78,5 +84,6 @@ public static class Program
|
||||
.BuildServiceProvider();
|
||||
|
||||
Ioc.Default.ConfigureServices(services);
|
||||
return services;
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
"profiles": {
|
||||
"Snap.Hutao (Package)": {
|
||||
"commandName": "MsixPackage",
|
||||
"nativeDebugging": true
|
||||
"nativeDebugging": false
|
||||
},
|
||||
"Snap.Hutao (Unpackaged)": {
|
||||
"commandName": "Project"
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Service.Sign;
|
||||
|
||||
/// <summary>
|
||||
/// 签到服务
|
||||
/// </summary>
|
||||
[Obsolete("米游社官方限制了签到功能")]
|
||||
public interface ISignService
|
||||
{
|
||||
/// <summary>
|
||||
/// 异步全部签到
|
||||
/// </summary>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>任务</returns>
|
||||
Task<SignResult> SignForAllAsync(CancellationToken token);
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Service.Sign;
|
||||
|
||||
/// <summary>
|
||||
/// 签到操作结果
|
||||
/// </summary>
|
||||
public struct SignResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的签到操作结果
|
||||
/// </summary>
|
||||
/// <param name="totalCount">总次数</param>
|
||||
/// <param name="retryCount">重试次数</param>
|
||||
public SignResult(int totalCount, int retryCount, TimeSpan time)
|
||||
{
|
||||
TotalCount = totalCount;
|
||||
RetryCount = retryCount;
|
||||
Time = time;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 总次数
|
||||
/// </summary>
|
||||
public int TotalCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 重试次数
|
||||
/// </summary>
|
||||
public int RetryCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用时
|
||||
/// </summary>
|
||||
public TimeSpan Time { get; set; }
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Core.Diagnostics;
|
||||
using Snap.Hutao.Service.Abstraction;
|
||||
using Snap.Hutao.Web.Hoyolab.Takumi.Binding;
|
||||
using Snap.Hutao.Web.Hoyolab.Takumi.Event.BbsSignReward;
|
||||
using Snap.Hutao.Web.Response;
|
||||
|
||||
namespace Snap.Hutao.Service.Sign;
|
||||
|
||||
/// <summary>
|
||||
/// 签到服务
|
||||
/// </summary>
|
||||
[Obsolete("米游社官方限制了签到功能")]
|
||||
[Injection(InjectAs.Transient, typeof(ISignService))]
|
||||
internal class SignService : ISignService
|
||||
{
|
||||
private readonly IUserService userService;
|
||||
private readonly IInfoBarService infoBarService;
|
||||
private readonly SignClient signClient;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的签到服务
|
||||
/// </summary>
|
||||
/// <param name="userService">用户服务</param>
|
||||
/// <param name="infoBarService">信息条服务</param>
|
||||
/// <param name="signClient">签到客户端</param>
|
||||
public SignService(IUserService userService, IInfoBarService infoBarService, SignClient signClient)
|
||||
{
|
||||
this.userService = userService;
|
||||
this.infoBarService = infoBarService;
|
||||
this.signClient = signClient;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<SignResult> SignForAllAsync(CancellationToken token)
|
||||
{
|
||||
IEnumerable<Model.Binding.User>? users = await userService
|
||||
.GetUserCollectionAsync()
|
||||
.ConfigureAwait(false);
|
||||
Queue<UserRole> userRolesQueue = GetSignQueue(users);
|
||||
|
||||
int totalCount = 0;
|
||||
int retryCount = 0;
|
||||
ValueStopwatch stopwatch = ValueStopwatch.StartNew();
|
||||
|
||||
while (userRolesQueue.TryDequeue(out UserRole current))
|
||||
{
|
||||
totalCount++;
|
||||
Response<SignInResult>? resp = await signClient
|
||||
.SignAsync(current, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
Must.NotNull(resp!);
|
||||
|
||||
if (resp.Data != null)
|
||||
{
|
||||
Must.Argument(resp.ReturnCode == 0, "返回代码应为 0");
|
||||
|
||||
// Geetest applied
|
||||
if (resp.Data.Success != 0)
|
||||
{
|
||||
userRolesQueue.Enqueue(current);
|
||||
retryCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
infoBarService.Information($"[{current.Role}] 签到成功");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ((KnownReturnCode)resp.ReturnCode)
|
||||
{
|
||||
case KnownReturnCode.OK:
|
||||
infoBarService.Information($"[{current.Role}] 签到成功");
|
||||
break;
|
||||
case KnownReturnCode.NotLoggedIn:
|
||||
case KnownReturnCode.AlreadySignedIn:
|
||||
infoBarService.Information($"[{current.Role}] {resp.Message}");
|
||||
break;
|
||||
case KnownReturnCode.InvalidRequest:
|
||||
infoBarService.Information("米游社SALT过期,请更新胡桃");
|
||||
break;
|
||||
default:
|
||||
throw Must.NeverHappen();
|
||||
}
|
||||
}
|
||||
|
||||
if (userRolesQueue.Count > 0)
|
||||
{
|
||||
int seconds = Random.Shared.Next(5, 15);
|
||||
await Task
|
||||
.Delay(TimeSpan.FromSeconds(seconds), token)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
return new(totalCount, retryCount, stopwatch.GetElapsedTime());
|
||||
}
|
||||
|
||||
private static Queue<UserRole> GetSignQueue(IEnumerable<Model.Binding.User> users)
|
||||
{
|
||||
Queue<UserRole> queue = new();
|
||||
|
||||
foreach (Model.Binding.User user in users)
|
||||
{
|
||||
foreach (UserGameRole role in user.UserGameRoles)
|
||||
{
|
||||
queue.Enqueue(new(user, role));
|
||||
}
|
||||
}
|
||||
|
||||
return queue;
|
||||
}
|
||||
}
|
||||
@@ -193,4 +193,7 @@
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Web\Hoyolab\Takumi\Event\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@@ -176,7 +176,7 @@ internal class UserViewModel : ObservableObject
|
||||
DataPackage content = new();
|
||||
content.SetText(Must.NotNull(user.Cookie!));
|
||||
Clipboard.SetContent(content);
|
||||
|
||||
Clipboard.Flush();
|
||||
infoBarService.Success($"{user.UserInfo!.Nickname} 的 Cookie 复制成功");
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
@@ -38,7 +38,6 @@ internal class UserClient
|
||||
public async Task<UserInfo?> GetUserFullInfoAsync(Model.Binding.User user, CancellationToken token = default)
|
||||
{
|
||||
Response<UserFullInfoWrapper>? resp = await httpClient
|
||||
.UsingDynamicSecret()
|
||||
.SetUser(user)
|
||||
.GetFromJsonAsync<Response<UserFullInfoWrapper>>(ApiEndpoints.UserFullInfo, jsonSerializerOptions, token)
|
||||
.ConfigureAwait(false);
|
||||
@@ -56,7 +55,6 @@ internal class UserClient
|
||||
public async Task<UserInfo?> GetUserFullInfoAsync(Model.Binding.User user, string uid, CancellationToken token = default)
|
||||
{
|
||||
Response<UserFullInfoWrapper>? resp = await httpClient
|
||||
.UsingDynamicSecret()
|
||||
.SetUser(user)
|
||||
.GetFromJsonAsync<Response<UserFullInfoWrapper>>(ApiEndpoints.UserFullInfoQuery(uid), jsonSerializerOptions, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Core.Convert;
|
||||
using System.Text;
|
||||
|
||||
namespace Snap.Hutao.Web.Hoyolab.DynamicSecret;
|
||||
|
||||
/// <summary>
|
||||
/// 为MiHoYo接口请求器 <see cref="Requester"/> 提供动态密钥
|
||||
/// </summary>
|
||||
internal abstract class DynamicSecretProvider : Md5Convert
|
||||
{
|
||||
private const string RandomRange = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
|
||||
|
||||
/// <summary>
|
||||
/// 创建动态密钥
|
||||
/// </summary>
|
||||
/// <returns>密钥</returns>
|
||||
public static string Create()
|
||||
{
|
||||
// unix timestamp
|
||||
long t = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||
|
||||
string r = GetRandomString();
|
||||
|
||||
string check = ToHexString($"salt={Core.CoreEnvironment.DynamicSecret1Salt}&t={t}&r={r}").ToLowerInvariant();
|
||||
|
||||
return $"{t},{r},{check}";
|
||||
}
|
||||
|
||||
private static string GetRandomString()
|
||||
{
|
||||
StringBuilder sb = new(6);
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
int pos = Random.Shared.Next(0, RandomRange.Length);
|
||||
sb.Append(RandomRange[pos]);
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ namespace Snap.Hutao.Web.Hoyolab.DynamicSecret;
|
||||
/// <summary>
|
||||
/// 为MiHoYo接口请求器 <see cref="Requester"/> 提供2代动态密钥
|
||||
/// </summary>
|
||||
internal abstract class DynamicSecretProvider2 : Md5Convert
|
||||
internal abstract class DynamicSecretProvider : Md5Convert
|
||||
{
|
||||
/// <summary>
|
||||
/// 创建动态密钥
|
||||
@@ -24,7 +24,7 @@ internal abstract class DynamicSecretProvider2 : Md5Convert
|
||||
long t = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||
|
||||
// random
|
||||
string r = GetRandomString();
|
||||
int r = GetRandom();
|
||||
|
||||
// body
|
||||
string b = postBody is null ? string.Empty : JsonSerializer.Serialize(postBody, options);
|
||||
@@ -38,7 +38,7 @@ internal abstract class DynamicSecretProvider2 : Md5Convert
|
||||
return $"{t},{r},{check}";
|
||||
}
|
||||
|
||||
private static string GetRandomString()
|
||||
private static int GetRandom()
|
||||
{
|
||||
// 原汁原味
|
||||
// v16 = time(0LL);
|
||||
@@ -49,11 +49,6 @@ internal abstract class DynamicSecretProvider2 : Md5Convert
|
||||
// else
|
||||
// v18 = v17 + 542367;
|
||||
int rand = Random.Shared.Next(100000, 200000);
|
||||
if (rand == 100000)
|
||||
{
|
||||
rand = 642367;
|
||||
}
|
||||
|
||||
return rand.ToString();
|
||||
return rand == 100000 ? 642367 : rand;
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ namespace Snap.Hutao.Web.Hoyolab.DynamicSecret.Http;
|
||||
/// 使用动态密钥2的Http客户端默认实现
|
||||
/// </summary>
|
||||
/// <typeparam name="TValue">请求提交的数据的的格式</typeparam>
|
||||
internal class DynamicSecret2HttpClient : IDynamicSecret2HttpClient
|
||||
internal class DynamicSecretHttpClient : IDynamicSecretHttpClient
|
||||
{
|
||||
private readonly HttpClient httpClient;
|
||||
private readonly JsonSerializerOptions options;
|
||||
@@ -23,13 +23,13 @@ internal class DynamicSecret2HttpClient : IDynamicSecret2HttpClient
|
||||
/// <param name="options">Json序列化选项</param>
|
||||
/// <param name="url">url</param>
|
||||
/// <param name="data">请求的数据</param>
|
||||
public DynamicSecret2HttpClient(HttpClient httpClient, JsonSerializerOptions options, string url)
|
||||
public DynamicSecretHttpClient(HttpClient httpClient, JsonSerializerOptions options, string url)
|
||||
{
|
||||
this.httpClient = httpClient;
|
||||
this.options = options;
|
||||
this.url = url;
|
||||
|
||||
httpClient.DefaultRequestHeaders.Set("DS", DynamicSecretProvider2.Create(options, url, null));
|
||||
httpClient.DefaultRequestHeaders.Set("DS", DynamicSecretProvider.Create(options, url, null));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -44,7 +44,7 @@ internal class DynamicSecret2HttpClient : IDynamicSecret2HttpClient
|
||||
/// </summary>
|
||||
/// <typeparam name="TValue">请求提交的数据的的格式</typeparam>
|
||||
[SuppressMessage("", "SA1402")]
|
||||
internal class DynamicSecret2HttpClient<TValue> : IDynamicSecret2HttpClient<TValue>
|
||||
internal class DynamicSecretHttpClient<TValue> : IDynamicSecretHttpClient<TValue>
|
||||
where TValue : class
|
||||
{
|
||||
private readonly HttpClient httpClient;
|
||||
@@ -59,14 +59,14 @@ internal class DynamicSecret2HttpClient<TValue> : IDynamicSecret2HttpClient<TVal
|
||||
/// <param name="options">Json序列化选项</param>
|
||||
/// <param name="url">url</param>
|
||||
/// <param name="data">请求的数据</param>
|
||||
public DynamicSecret2HttpClient(HttpClient httpClient, JsonSerializerOptions options, string url, TValue? data)
|
||||
public DynamicSecretHttpClient(HttpClient httpClient, JsonSerializerOptions options, string url, TValue? data)
|
||||
{
|
||||
this.httpClient = httpClient;
|
||||
this.options = options;
|
||||
this.url = url;
|
||||
this.data = data;
|
||||
|
||||
httpClient.DefaultRequestHeaders.Set("DS", DynamicSecretProvider2.Create(options, url, data));
|
||||
httpClient.DefaultRequestHeaders.Set("DS", DynamicSecretProvider.Create(options, url, data));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -8,7 +8,7 @@ namespace Snap.Hutao.Web.Hoyolab.DynamicSecret.Http;
|
||||
/// <summary>
|
||||
/// 使用动态密钥2的Http客户端抽象
|
||||
/// </summary>
|
||||
internal interface IDynamicSecret2HttpClient
|
||||
internal interface IDynamicSecretHttpClient
|
||||
{
|
||||
/// <summary>
|
||||
/// Sends a GET request to the specified Uri and returns the value that results from deserializing the response body as JSON in an asynchronous operation.
|
||||
@@ -23,7 +23,7 @@ internal interface IDynamicSecret2HttpClient
|
||||
/// 使用动态密钥2的Http客户端抽象
|
||||
/// </summary>
|
||||
/// <typeparam name="TValue">请求数据的类型</typeparam>
|
||||
internal interface IDynamicSecret2HttpClient<TValue>
|
||||
internal interface IDynamicSecretHttpClient<TValue>
|
||||
where TValue : class
|
||||
{
|
||||
/// <summary>
|
||||
@@ -11,17 +11,6 @@ namespace Snap.Hutao.Web.Hoyolab.DynamicSecret;
|
||||
/// </summary>
|
||||
internal static class HttpClientDynamicSecretExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 使用动态密钥执行 GET 操作
|
||||
/// </summary>
|
||||
/// <param name="httpClient">请求器</param>
|
||||
/// <returns>响应</returns>
|
||||
public static HttpClient UsingDynamicSecret(this HttpClient httpClient)
|
||||
{
|
||||
httpClient.DefaultRequestHeaders.Set("DS", DynamicSecretProvider.Create());
|
||||
return httpClient;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用二代动态密钥执行 GET 操作
|
||||
/// </summary>
|
||||
@@ -29,9 +18,9 @@ internal static class HttpClientDynamicSecretExtensions
|
||||
/// <param name="options">选项</param>
|
||||
/// <param name="url">地址</param>
|
||||
/// <returns>响应</returns>
|
||||
public static IDynamicSecret2HttpClient UsingDynamicSecret2(this HttpClient httpClient, JsonSerializerOptions options, string url)
|
||||
public static IDynamicSecretHttpClient UsingDynamicSecret(this HttpClient httpClient, JsonSerializerOptions options, string url)
|
||||
{
|
||||
return new DynamicSecret2HttpClient(httpClient, options, url);
|
||||
return new DynamicSecretHttpClient(httpClient, options, url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -43,9 +32,9 @@ internal static class HttpClientDynamicSecretExtensions
|
||||
/// <param name="url">地址</param>
|
||||
/// <param name="data">post数据</param>
|
||||
/// <returns>响应</returns>
|
||||
public static IDynamicSecret2HttpClient<TValue> UsingDynamicSecret2<TValue>(this HttpClient httpClient, JsonSerializerOptions options, string url, TValue data)
|
||||
public static IDynamicSecretHttpClient<TValue> UsingDynamicSecret<TValue>(this HttpClient httpClient, JsonSerializerOptions options, string url, TValue data)
|
||||
where TValue : class
|
||||
{
|
||||
return new DynamicSecret2HttpClient<TValue>(httpClient, options, url, data);
|
||||
return new DynamicSecretHttpClient<TValue>(httpClient, options, url, data);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Web.Hoyolab.Takumi.Event.BbsSignReward;
|
||||
|
||||
/// <summary>
|
||||
/// 奖励物品
|
||||
/// </summary>
|
||||
public class Award
|
||||
{
|
||||
/// <summary>
|
||||
/// 图标
|
||||
/// </summary>
|
||||
[JsonPropertyName("icon")]
|
||||
public string Icon { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 名称
|
||||
/// </summary>
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 个数
|
||||
/// </summary>
|
||||
[JsonPropertyName("cnt")]
|
||||
public string Count { get; set; } = default!;
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Web.Hoyolab.Takumi.Event.BbsSignReward;
|
||||
|
||||
/// <summary>
|
||||
/// 奖励
|
||||
/// </summary>
|
||||
public class Reward
|
||||
{
|
||||
/// <summary>
|
||||
/// 月份
|
||||
/// </summary>
|
||||
[JsonPropertyName("month")]
|
||||
public string? Month { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 奖励列表
|
||||
/// </summary>
|
||||
[JsonPropertyName("awards")]
|
||||
public List<Award>? Awards { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 支持补签
|
||||
/// </summary>
|
||||
[JsonPropertyName("resign")]
|
||||
public bool Resign { get; set; }
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
|
||||
using Snap.Hutao.Model.Binding;
|
||||
using Snap.Hutao.Web.Hoyolab.DynamicSecret;
|
||||
using Snap.Hutao.Web.Hoyolab.Takumi.Binding;
|
||||
using Snap.Hutao.Web.Response;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Json;
|
||||
|
||||
namespace Snap.Hutao.Web.Hoyolab.Takumi.Event.BbsSignReward;
|
||||
|
||||
/// <summary>
|
||||
/// 签到客户端
|
||||
/// </summary>
|
||||
[HttpClient(HttpClientConfigration.XRpc)]
|
||||
internal class SignClient
|
||||
{
|
||||
private readonly HttpClient httpClient;
|
||||
private readonly JsonSerializerOptions options;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的签到客户端
|
||||
/// </summary>
|
||||
/// <param name="httpClient">http客户端</param>
|
||||
/// <param name="options">选项</param>
|
||||
public SignClient(HttpClient httpClient, JsonSerializerOptions options)
|
||||
{
|
||||
this.httpClient = httpClient;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步获取签到信息
|
||||
/// </summary>
|
||||
/// <param name="user">用户</param>
|
||||
/// <param name="role">角色</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>签到信息</returns>
|
||||
public async Task<SignInRewardInfo?> GetInfoAsync(User user, UserGameRole role, CancellationToken token = default)
|
||||
{
|
||||
Response<SignInRewardInfo>? resp = await httpClient
|
||||
.SetUser(user)
|
||||
.UsingDynamicSecret()
|
||||
.GetFromJsonAsync<Response<SignInRewardInfo>>(ApiEndpoints.SignInRewardInfo((PlayerUid)role), options, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return resp?.Data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步获取签到信息
|
||||
/// </summary>
|
||||
/// <param name="user">用户</param>
|
||||
/// <param name="role">角色</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>签到信息</returns>
|
||||
public async Task<SignInRewardReSignInfo?> GetResignInfoAsync(User user, UserGameRole role, CancellationToken token = default)
|
||||
{
|
||||
Response<SignInRewardReSignInfo>? resp = await httpClient
|
||||
.SetUser(user)
|
||||
.UsingDynamicSecret()
|
||||
.GetFromJsonAsync<Response<SignInRewardReSignInfo>>(ApiEndpoints.SignInRewardResignInfo((PlayerUid)role), options, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return resp?.Data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取签到奖励
|
||||
/// </summary>
|
||||
/// <param name="user">用户</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>奖励信息</returns>
|
||||
public async Task<Reward?> GetRewardAsync(User user, CancellationToken token = default)
|
||||
{
|
||||
Response<Reward>? resp = await httpClient
|
||||
.SetUser(user)
|
||||
.GetFromJsonAsync<Response<Reward>>(ApiEndpoints.SignInRewardHome, options, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return resp?.Data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 补签
|
||||
/// </summary>
|
||||
/// <param name="userRole">用户角色</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>签到结果</returns>
|
||||
public Task<Response<SignInResult>?> ReSignAsync(UserRole userRole, CancellationToken token = default)
|
||||
{
|
||||
return ReSignAsync(userRole.User, userRole.Role, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 补签
|
||||
/// </summary>
|
||||
/// <param name="user">用户</param>
|
||||
/// <param name="role">角色</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>签到消息</returns>
|
||||
public async Task<Response<SignInResult>?> ReSignAsync(User user, UserGameRole role, CancellationToken token = default)
|
||||
{
|
||||
SignInData data = new((PlayerUid)role);
|
||||
|
||||
HttpResponseMessage response = await httpClient
|
||||
.SetUser(user)
|
||||
.UsingDynamicSecret()
|
||||
.PostAsJsonAsync(ApiEndpoints.SignInRewardReSign, data, options, token)
|
||||
.ConfigureAwait(false);
|
||||
Response<SignInResult>? resp = await response.Content
|
||||
.ReadFromJsonAsync<Response<SignInResult>>(options, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 签到
|
||||
/// </summary>
|
||||
/// <param name="userRole">用户角色</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>签到结果</returns>
|
||||
public Task<Response<SignInResult>?> SignAsync(UserRole userRole, CancellationToken token = default)
|
||||
{
|
||||
return SignAsync(userRole.User, userRole.Role, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 签到
|
||||
/// </summary>
|
||||
/// <param name="user">用户</param>
|
||||
/// <param name="role">角色</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>签到结果</returns>
|
||||
public async Task<Response<SignInResult>?> SignAsync(User user, UserGameRole role, CancellationToken token = default)
|
||||
{
|
||||
HttpResponseMessage response = await httpClient
|
||||
.SetUser(user)
|
||||
.UsingDynamicSecret()
|
||||
.PostAsJsonAsync(ApiEndpoints.SignInRewardSign, new SignInData((PlayerUid)role), options, token)
|
||||
.ConfigureAwait(false);
|
||||
Response<SignInResult>? resp = await response.Content
|
||||
.ReadFromJsonAsync<Response<SignInResult>>(options, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return resp;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Web.Hoyolab.Takumi.Event.BbsSignReward;
|
||||
|
||||
/// <summary>
|
||||
/// 签到提交数据
|
||||
/// </summary>
|
||||
public class SignInData
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的签到提交数据
|
||||
/// </summary>
|
||||
/// <param name="uid">uid</param>
|
||||
public SignInData(PlayerUid uid)
|
||||
{
|
||||
Region = uid.Region;
|
||||
Uid = uid.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 活动Id
|
||||
/// </summary>
|
||||
[JsonPropertyName("act_id")]
|
||||
public string ActivityId { get; } = ApiEndpoints.SignInRewardActivityId;
|
||||
|
||||
/// <summary>
|
||||
/// 地区代码
|
||||
/// </summary>
|
||||
[JsonPropertyName("region")]
|
||||
public string Region { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Uid
|
||||
/// </summary>
|
||||
[JsonPropertyName("uid")]
|
||||
public string Uid { get; }
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Web.Hoyolab.Takumi.Event.BbsSignReward;
|
||||
|
||||
/// <summary>
|
||||
/// 签到结果
|
||||
/// https://docs.geetest.com/sensebot/apirefer/api/server
|
||||
/// </summary>
|
||||
public class SignInResult
|
||||
{
|
||||
/// <summary>
|
||||
/// ???
|
||||
/// </summary>
|
||||
[JsonPropertyName("code")]
|
||||
public string Code { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 风控码 375
|
||||
/// </summary>
|
||||
[JsonPropertyName("risk_code")]
|
||||
public int RiskCode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// geetest appid
|
||||
/// </summary>
|
||||
[JsonPropertyName("gt")]
|
||||
public string Gt { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// geetest challenge id
|
||||
/// </summary>
|
||||
[JsonPropertyName("challenge")]
|
||||
public string Challenge { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// geetest 服务状态
|
||||
/// </summary>
|
||||
[JsonPropertyName("success")]
|
||||
public int Success { get; set; }
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Web.Hoyolab.Takumi.Event.BbsSignReward;
|
||||
|
||||
/// <summary>
|
||||
/// 签到信息
|
||||
/// </summary>
|
||||
public class SignInRewardInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 累积签到天数
|
||||
/// </summary>
|
||||
[JsonPropertyName("total_sign_day")]
|
||||
public int TotalSignDay { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// yyyy-MM-dd
|
||||
/// </summary>
|
||||
[JsonPropertyName("today")]
|
||||
public string? Today { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 今日是否已签到
|
||||
/// </summary>
|
||||
[JsonPropertyName("is_sign")]
|
||||
public bool IsSign { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ?
|
||||
/// </summary>
|
||||
[JsonPropertyName("is_sub")]
|
||||
public bool IsSub { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否首次绑定
|
||||
/// </summary>
|
||||
[JsonPropertyName("first_bind")]
|
||||
public bool FirstBind { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否为当月第一次
|
||||
/// </summary>
|
||||
[JsonPropertyName("month_first")]
|
||||
public bool MonthFirst { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 漏签天数
|
||||
/// </summary>
|
||||
[JsonPropertyName("sign_cnt_missed")]
|
||||
public bool SignCountMissed { get; set; }
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Web.Hoyolab.Takumi.Event.BbsSignReward;
|
||||
|
||||
/// <summary>
|
||||
/// 补签说明
|
||||
/// </summary>
|
||||
public class SignInRewardReSignInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 当日补签次数
|
||||
/// </summary>
|
||||
[JsonPropertyName("resign_cnt_daily")]
|
||||
public bool ResignCountDaily { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当月补签次数
|
||||
/// </summary>
|
||||
[JsonPropertyName("resign_cnt_monthly")]
|
||||
public bool ResignCountMonthly { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当日补签次数限制
|
||||
/// </summary>
|
||||
[JsonPropertyName("resign_limit_daily")]
|
||||
public bool ResignLimitDaily { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当月补签次数限制
|
||||
/// </summary>
|
||||
[JsonPropertyName("resign_limit_monthly")]
|
||||
public bool ResignLimitMonthly { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 漏签次数
|
||||
/// </summary>
|
||||
[JsonPropertyName("sign_cnt_missed")]
|
||||
public bool SignCountMissed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 米游币个数
|
||||
/// </summary>
|
||||
[JsonPropertyName("coin_cnt")]
|
||||
public bool CoinCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 补签需要的米游币个数
|
||||
/// </summary>
|
||||
[JsonPropertyName("coin_cost")]
|
||||
public bool CoinCost { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 规则
|
||||
/// </summary>
|
||||
[JsonPropertyName("rule")]
|
||||
public string Rule { get; set; } = default!;
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Binding;
|
||||
using Snap.Hutao.Web.Hoyolab.Takumi.Binding;
|
||||
|
||||
namespace Snap.Hutao.Web.Hoyolab.Takumi.Event.BbsSignReward;
|
||||
|
||||
/// <summary>
|
||||
/// 将用户与角色捆绑在一起
|
||||
/// </summary>
|
||||
public struct UserRole
|
||||
{
|
||||
/// <summary>
|
||||
/// 构造一个新的用户角色
|
||||
/// </summary>
|
||||
/// <param name="user">用户</param>
|
||||
/// <param name="role">角色</param>
|
||||
public UserRole(User user, UserGameRole role)
|
||||
{
|
||||
User = user;
|
||||
Role = role;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用户
|
||||
/// </summary>
|
||||
public User User { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 角色
|
||||
/// </summary>
|
||||
public UserGameRole Role { get; set; }
|
||||
}
|
||||
@@ -56,7 +56,7 @@ internal class GameRecordClient
|
||||
{
|
||||
Response<PlayerInfo>? resp = await httpClient
|
||||
.SetUser(user)
|
||||
.UsingDynamicSecret2(jsonSerializerOptions, ApiEndpoints.GameRecordIndex(uid.Value, uid.Region))
|
||||
.UsingDynamicSecret(jsonSerializerOptions, ApiEndpoints.GameRecordIndex(uid.Value, uid.Region))
|
||||
.GetFromJsonAsync<Response<PlayerInfo>>(token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
@@ -88,7 +88,7 @@ internal class GameRecordClient
|
||||
{
|
||||
Response<SpiralAbyss.SpiralAbyss>? resp = await httpClient
|
||||
.SetUser(user)
|
||||
.UsingDynamicSecret2(jsonSerializerOptions, ApiEndpoints.GameRecordSpiralAbyss(schedule, uid))
|
||||
.UsingDynamicSecret(jsonSerializerOptions, ApiEndpoints.GameRecordSpiralAbyss(schedule, uid))
|
||||
.GetFromJsonAsync<Response<SpiralAbyss.SpiralAbyss>>(token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
@@ -122,7 +122,7 @@ internal class GameRecordClient
|
||||
|
||||
HttpResponseMessage? response = await httpClient
|
||||
.SetUser(user)
|
||||
.UsingDynamicSecret2(jsonSerializerOptions, ApiEndpoints.GameRecordCharacter, data)
|
||||
.UsingDynamicSecret(jsonSerializerOptions, ApiEndpoints.GameRecordCharacter, data)
|
||||
.PostAsJsonAsync(token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
|
||||
@@ -18,10 +18,30 @@ public enum KnownReturnCode : int
|
||||
/// </summary>
|
||||
AlreadySignedIn = -5003,
|
||||
|
||||
/// <summary>
|
||||
/// 需要风险验证
|
||||
/// </summary>
|
||||
RET_NEED_RISK_VERIFY = -3235,
|
||||
|
||||
/// <summary>
|
||||
/// 禁止
|
||||
/// </summary>
|
||||
RET_AIGIS_FAILED = -3202,
|
||||
|
||||
/// <summary>
|
||||
/// Ban
|
||||
/// </summary>
|
||||
RET_BAN = -3201,
|
||||
|
||||
/// <summary>
|
||||
/// 需要地理验证
|
||||
/// </summary>
|
||||
RET_NEED_AIGIS = -3101,
|
||||
|
||||
/// <summary>
|
||||
/// 尚未登录
|
||||
/// </summary>
|
||||
NotLoggedIn = -100,
|
||||
RET_TOKEN_INVALID = -100,
|
||||
|
||||
/// <summary>
|
||||
/// 验证密钥过期
|
||||
@@ -31,7 +51,7 @@ public enum KnownReturnCode : int
|
||||
/// <summary>
|
||||
/// Ok
|
||||
/// </summary>
|
||||
OK = 0,
|
||||
RET_SUCCESS = 0,
|
||||
|
||||
/// <summary>
|
||||
/// 未定义
|
||||
|
||||
@@ -88,4 +88,14 @@ public class Response<TData> : Response
|
||||
/// </summary>
|
||||
[JsonPropertyName("data")]
|
||||
public TData? Data { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
int j = ReturnCode.GetHashCode();
|
||||
int k = Message == null ? 0 : Message.GetHashCode();
|
||||
int i = Data == null ? 0 : Data.GetHashCode();
|
||||
|
||||
return (((j * 31) + k) * 31) + i;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user