mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
Merge pull request #988 from DGP-Studio/main
This commit is contained in:
7
.github/workflows/qodana_code_quality.yml
vendored
7
.github/workflows/qodana_code_quality.yml
vendored
@@ -5,6 +5,11 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- develop
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- '**.yml'
|
||||
- '**.resx'
|
||||
|
||||
jobs:
|
||||
qodana:
|
||||
@@ -15,5 +20,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
- name: 'Qodana Scan'
|
||||
uses: JetBrains/qodana-action@v2023.2
|
||||
with:
|
||||
pr-mode: false
|
||||
env:
|
||||
QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
|
||||
72
CONTRIBUTING.md
Normal file
72
CONTRIBUTING.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# Contribution Guide
|
||||
|
||||
## Contribute Your Code
|
||||
|
||||
### Setup Snap.Hutao Project
|
||||
|
||||
1. Download and install [Visual Studio 2022 Community](https://visualstudio.microsoft.com/downloads/)
|
||||
2. Open Visual Studio Installer to complete Visual Studio installation
|
||||
- You need to install `.NET desktop development`, `Desktop development with C++` and `Universal Windows Platform development` components
|
||||
3. Install `Single-project MSIX Packaging Tools for VS 2022` provided by Microsoft in Visual Studio marketplace
|
||||
4. Use git to clone the project `https://github.com/DGP-Studio/Snap.Hutao.git` to your local device
|
||||
5. Switch git branch to `develop`
|
||||
6. Open project solution with your Visual Studio and then you are ready to go
|
||||
|
||||
### Start Pull Request
|
||||
|
||||
- All code-related changes from authors' own branches are only allowed be merged to `develop` branch
|
||||
- Please use [keywords](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/using-keywords-in-issues-and-pull-requests) to link your PR or commits with issues, so issues can be automatically closed once commits are merged into `main` branch.
|
||||
|
||||
### Test Binary Package
|
||||
|
||||
Once the code in updated in `develop` and `main` branches, an Azure Pipeline CI script will build the latest code to `Snap Hutao Alpha` package. Once the package is built, it will be released on [GitHub Release page](https://github.com/DGP-Studio/Snap.Hutao/releases) as a pre-released package.
|
||||
|
||||
You need to install [Snap.Hutao.CI.cer](https://github.com/DGP-Studio/Snap.Hutao/releases/download/2023.10.3.1/Snap.Hutao.CI.cer) certificate to your local machine, and then install the msix package in the release.
|
||||
|
||||
*If the latest release does not contains attached file, that means package is still in uploading process.
|
||||
|
||||
## Start New Issue
|
||||
|
||||
To help users solve problems faster and increase developers' efficiency in solving problems, Snap Hutao provides detailed documentation to explain common problems and issue templates to guide users to report program problems by submitting issues.
|
||||
|
||||
Before submitting a new issue, you should check the following pages:
|
||||
|
||||
- [FAQ](https://hut.ao/advanced/FAQ.html) Document
|
||||
- [Common Program Exceptions ](https://hut.ao/en/advanced/exceptions.html)Document
|
||||
- [Current Opened BUG Report Issues](https://github.com/DGP-Studio/Snap.Hutao/issues?q=is%3Aissue+is%3Aopen+label%3ABUG)
|
||||
|
||||
When starting a new issue, please use the issue templates:
|
||||
|
||||
- Describe your issue in details to help developers to reproduce the issue
|
||||
- Your description of reproduction should be a step-by-step story
|
||||
- If your issue is about program crash
|
||||
- Remember to provide your Device ID
|
||||
- Check Windows Event Viewer, and attach associated `.NET Error` details in the issue body
|
||||
|
||||
## Document Modification
|
||||
|
||||
Snap Hutao Document site is stored in repository [DGP-Studio/Snap.Hutao.Docs](https://github.com/DGP-Studio/Snap.Hutao.Docs), you can process the following steps to test the site in your local device:
|
||||
|
||||
1. Download and install [NodeJS 18](https://nodejs.org/en/download/)
|
||||
2. Clone the repository
|
||||
3. Run `npm install` in the root directory of the document project
|
||||
4. Run `npm run docs:dev` to start test on 8080 port
|
||||
|
||||
### Localization
|
||||
|
||||
Snap.Hutao.Docs project structure is designed as multiple languages site. Each language has its independent folder under `docs` directory.
|
||||
|
||||
**If you wish to add another language document, you can [start an issue in document repository](https://github.com/DGP-Studio/Snap.Hutao.Docs/issues) to ask developer to setup an environment for you, or you can process the following steps by yourself:**
|
||||
|
||||
1. make a copy of `zh` folder, rename the new folder as the new language's code
|
||||
2. Start your translation work in the new language folder
|
||||
3. In `docs/.vuepress/sidebar` folder, duplicate `zh.ts` file
|
||||
1. Rename the file to `{language_code}.ts`
|
||||
2. In the line 4, change `/zh/` to `/{language_code}/`
|
||||
3. Translate all `text` field
|
||||
4. In `docs/.vuepress/navbar` folder, duplicate `zh.ts` file
|
||||
1. Rename the file to `{language_code}.ts`
|
||||
2. Replace all `/zh/` to `/{language_code}/`
|
||||
3. Translate all `text` field
|
||||
5. In `docs/.vuepress/config.ts`file, add your language information in `locales` and `plugins/docsearchPlugin/locales` dictionary
|
||||
6. In `docs/.vuepress/theme.ts`file, add your language information in `locales` dictionary
|
||||
@@ -18,7 +18,10 @@ exclude:
|
||||
paths:
|
||||
- Snap.Hutao.Test
|
||||
- Snap.Hutao.SourceGeneration
|
||||
|
||||
- name: All
|
||||
paths:
|
||||
- Snap.Hutao.SourceGeneration
|
||||
- Snap.Hutao.Test
|
||||
#Execute shell command before Qodana execution (Applied in CI/CD pipeline)
|
||||
#bootstrap: sh ./prepare-qodana.sh
|
||||
|
||||
@@ -27,4 +30,4 @@ exclude:
|
||||
# - id: <plugin.id> #(plugin id can be found at https://plugins.jetbrains.com)
|
||||
|
||||
#Specify Qodana linter for analysis (Applied in CI/CD pipeline)
|
||||
linter: jetbrains/qodana-dotnet:latest
|
||||
linter: jetbrains/qodana-dotnet:2023.2-eap
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Snap.Hutao.Core.DependencyInjection.Abstraction;
|
||||
using Snap.Hutao.ViewModel.User;
|
||||
using Snap.Hutao.Web.Hoyolab.Takumi.Event.BbsSignReward;
|
||||
using Snap.Hutao.Web.Response;
|
||||
@@ -15,7 +17,9 @@ internal sealed partial class SignInService : ISignInService
|
||||
|
||||
public async ValueTask<ValueResult<bool, string>> ClaimRewardAsync(UserAndUid userAndUid, CancellationToken token = default)
|
||||
{
|
||||
SignInClient signInClient = serviceProvider.GetRequiredService<SignInClient>();
|
||||
ISignInClient signInClient = serviceProvider
|
||||
.GetRequiredService<IOverseaSupportFactory<ISignInClient>>()
|
||||
.Create(userAndUid.User.IsOversea);
|
||||
|
||||
Response<Reward> rewardResponse = await signInClient.GetRewardAsync(userAndUid.User, token).ConfigureAwait(false);
|
||||
|
||||
|
||||
@@ -229,6 +229,49 @@ internal static class ApiOsEndpoints
|
||||
|
||||
#endregion
|
||||
|
||||
#region SgHk4eApi
|
||||
|
||||
/// <summary>
|
||||
/// 签到活动Id
|
||||
/// </summary>
|
||||
public const string SignInRewardActivityId = "e202102251931481";
|
||||
|
||||
/// <summary>
|
||||
/// 签到
|
||||
/// </summary>
|
||||
public const string SignInRewardSign = $"{SgHk4eApi}/event/sol/sign?lang=zh-cn";
|
||||
|
||||
/// <summary>
|
||||
/// 签到
|
||||
/// </summary>
|
||||
public const string SignInRewardHome = $"{SgHk4eApi}/event/sol/home?lang=zh-cn&act_id={SignInRewardActivityId}";
|
||||
|
||||
/// <summary>
|
||||
/// 补签
|
||||
/// </summary>
|
||||
public const string SignInRewardReSign = $"{SgHk4eApi}/event/sol/resign?lang=zh-cn";
|
||||
|
||||
/// <summary>
|
||||
/// 补签信息
|
||||
/// </summary>
|
||||
/// <param name="uid">uid</param>
|
||||
/// <returns>补签信息字符串</returns>
|
||||
public static string SignInRewardResignInfo(in PlayerUid uid)
|
||||
{
|
||||
return $"{SgHk4eApi}/event/sol/resign_info?lang=zh-cn&act_id={SignInRewardActivityId}®ion={uid.Region}&uid={uid.Value}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 签到信息
|
||||
/// </summary>
|
||||
/// <param name="uid">uid</param>
|
||||
/// <returns>签到信息字符串</returns>
|
||||
public static string SignInRewardInfo(in PlayerUid uid)
|
||||
{
|
||||
return $"{SgHk4eApi}/event/sol/info?lang=zh-cn&act_id={SignInRewardActivityId}®ion={uid.Region}&uid={uid.Value}";
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region SdkStaticLauncherApi
|
||||
|
||||
/// <summary>
|
||||
@@ -270,6 +313,7 @@ internal static class ApiOsEndpoints
|
||||
private const string SdkOsStaticLauncherApi = $"{SdkOsStatic}/hk4e_global/mdk/launcher/api";
|
||||
|
||||
private const string SgPublicApi = "https://sg-public-api.hoyoverse.com";
|
||||
private const string SgHk4eApi = "https://sg-hk4e-api.hoyoverse.com";
|
||||
|
||||
private const string WebApiOs = "https://webapi-os.account.hoyoverse.com";
|
||||
private const string WebApiOsAccountApi = $"{WebApiOs}/Api";
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.ViewModel.User;
|
||||
using Snap.Hutao.Web.Response;
|
||||
|
||||
namespace Snap.Hutao.Web.Hoyolab.Takumi.Event.BbsSignReward;
|
||||
|
||||
/// <summary>
|
||||
/// 每日签到客户端接口
|
||||
/// </summary>
|
||||
internal interface ISignInClient
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取
|
||||
/// </summary>
|
||||
/// <param name="user">用户信息</param>
|
||||
/// <param name="token">token</param>
|
||||
/// <returns>结果</returns>
|
||||
ValueTask<Response<Reward>> GetRewardAsync(Model.Entity.User user, CancellationToken token = default);
|
||||
|
||||
/// <summary>
|
||||
/// 签到
|
||||
/// </summary>
|
||||
/// <param name="userAndUid">用户信息</param>
|
||||
/// <param name="token">token</param>
|
||||
/// <returns>签到结果</returns>
|
||||
ValueTask<Response<SignInResult>> SignAsync(UserAndUid userAndUid, CancellationToken token = default);
|
||||
}
|
||||
@@ -17,7 +17,7 @@ namespace Snap.Hutao.Web.Hoyolab.Takumi.Event.BbsSignReward;
|
||||
[UseDynamicSecret]
|
||||
[HttpClient(HttpClientConfiguration.XRpc)]
|
||||
[PrimaryHttpMessageHandler(UseCookies = false)]
|
||||
internal sealed partial class SignInClient
|
||||
internal sealed partial class SignInClient : ISignInClient
|
||||
{
|
||||
private readonly HttpClient httpClient;
|
||||
private readonly HomaGeetestClient homaGeetestClient;
|
||||
@@ -58,7 +58,7 @@ internal sealed partial class SignInClient
|
||||
|
||||
public async ValueTask<Response<SignInResult>> ReSignAsync(UserAndUid userAndUid, CancellationToken token = default)
|
||||
{
|
||||
SignInData data = new(userAndUid.Uid);
|
||||
SignInData data = new(userAndUid.Uid, false);
|
||||
|
||||
Response<SignInResult>? resp = await httpClient
|
||||
.SetUser(userAndUid.User, CookieType.CookieToken)
|
||||
@@ -74,7 +74,7 @@ internal sealed partial class SignInClient
|
||||
Response<SignInResult>? resp = await httpClient
|
||||
.SetUser(userAndUid.User, CookieType.CookieToken)
|
||||
.UseDynamicSecret(DynamicSecretVersion.Gen1, SaltType.LK2, false)
|
||||
.TryCatchPostAsJsonAsync<SignInData, Response<SignInResult>>(ApiEndpoints.SignInRewardSign, new(userAndUid.Uid), options, logger, token)
|
||||
.TryCatchPostAsJsonAsync<SignInData, Response<SignInResult>>(ApiEndpoints.SignInRewardSign, new(userAndUid.Uid, false), options, logger, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (resp is { Data: { Success: 1, Gt: string gt, Challenge: string originChallenge } })
|
||||
@@ -87,7 +87,7 @@ internal sealed partial class SignInClient
|
||||
.SetUser(userAndUid.User, CookieType.CookieToken)
|
||||
.SetXrpcChallenge(challenge, validate)
|
||||
.UseDynamicSecret(DynamicSecretVersion.Gen1, SaltType.LK2, false)
|
||||
.TryCatchPostAsJsonAsync<SignInData, Response<SignInResult>>(ApiEndpoints.SignInRewardSign, new(userAndUid.Uid), options, logger, token)
|
||||
.TryCatchPostAsJsonAsync<SignInData, Response<SignInResult>>(ApiEndpoints.SignInRewardSign, new(userAndUid.Uid, false), options, logger, token)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Core.DependencyInjection.Abstraction;
|
||||
|
||||
namespace Snap.Hutao.Web.Hoyolab.Takumi.Event.BbsSignReward;
|
||||
|
||||
[ConstructorGenerated(CallBaseConstructor = true)]
|
||||
[Injection(InjectAs.Transient, typeof(IOverseaSupportFactory<ISignInClient>))]
|
||||
internal sealed partial class SignInClientFactory : OverseaSupportFactory<ISignInClient, SignInClient, SignInClientOversea>
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
|
||||
using Snap.Hutao.ViewModel.User;
|
||||
using Snap.Hutao.Web.Hoyolab.DynamicSecret;
|
||||
using Snap.Hutao.Web.Hutao.Geetest;
|
||||
using Snap.Hutao.Web.Response;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace Snap.Hutao.Web.Hoyolab.Takumi.Event.BbsSignReward;
|
||||
|
||||
/// <summary>
|
||||
/// Global签到客户端
|
||||
/// </summary>
|
||||
[ConstructorGenerated(ResolveHttpClient = true)]
|
||||
[UseDynamicSecret]
|
||||
[HttpClient(HttpClientConfiguration.Default)]
|
||||
[PrimaryHttpMessageHandler(UseCookies = false)]
|
||||
internal sealed partial class SignInClientOversea : ISignInClient
|
||||
{
|
||||
private readonly HttpClient httpClient;
|
||||
private readonly HomaGeetestClient homaGeetestClient;
|
||||
private readonly JsonSerializerOptions options;
|
||||
private readonly ILogger<SignInClient> logger;
|
||||
|
||||
public async ValueTask<Response<Reward>> GetRewardAsync(Model.Entity.User user, CancellationToken token = default)
|
||||
{
|
||||
Response<Reward>? resp = await httpClient
|
||||
.SetUser(user, CookieType.CookieToken)
|
||||
.TryCatchGetFromJsonAsync<Response<Reward>>(ApiOsEndpoints.SignInRewardHome, options, logger, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return Response.Response.DefaultIfNull(resp);
|
||||
}
|
||||
|
||||
public async ValueTask<Response<SignInResult>> SignAsync(UserAndUid userAndUid, CancellationToken token = default)
|
||||
{
|
||||
Response<SignInResult>? resp = await httpClient
|
||||
.SetUser(userAndUid.User, CookieType.CookieToken)
|
||||
.TryCatchPostAsJsonAsync<SignInData, Response<SignInResult>>(ApiOsEndpoints.SignInRewardSign, new(userAndUid.Uid, true), options, logger, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (resp is { Data: { Success: 1, Gt: string gt, Challenge: string originChallenge } })
|
||||
{
|
||||
GeetestResponse verifyResponse = await homaGeetestClient.VerifyAsync(gt, originChallenge, token).ConfigureAwait(false);
|
||||
|
||||
if (verifyResponse is { Code: 0, Data: { Validate: string validate, Challenge: string challenge } })
|
||||
{
|
||||
resp = await httpClient
|
||||
.SetUser(userAndUid.User, CookieType.CookieToken)
|
||||
.SetXrpcChallenge(challenge, validate)
|
||||
.TryCatchPostAsJsonAsync<SignInData, Response<SignInResult>>(ApiOsEndpoints.SignInRewardSign, new(userAndUid.Uid, true), options, logger, token)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
resp.ReturnCode = resp.Data.RiskCode;
|
||||
resp.Message = SH.ServiceSignInRiskVerificationFailed;
|
||||
}
|
||||
}
|
||||
|
||||
return Response.Response.DefaultIfNull(resp);
|
||||
}
|
||||
}
|
||||
@@ -12,9 +12,11 @@ internal sealed class SignInData
|
||||
/// 构造一个新的签到提交数据
|
||||
/// </summary>
|
||||
/// <param name="uid">uid</param>
|
||||
/// <param name="isOversea">是否为国际服,用于选择ActivityId</param>
|
||||
[SuppressMessage("", "SH002")]
|
||||
public SignInData(PlayerUid uid)
|
||||
public SignInData(PlayerUid uid, bool isOversea)
|
||||
{
|
||||
ActivityId = isOversea ? ApiOsEndpoints.SignInRewardActivityId : ApiEndpoints.SignInRewardActivityId;
|
||||
Region = uid.Region;
|
||||
Uid = uid.Value;
|
||||
}
|
||||
@@ -23,7 +25,7 @@ internal sealed class SignInData
|
||||
/// 活动Id
|
||||
/// </summary>
|
||||
[JsonPropertyName("act_id")]
|
||||
public string ActivityId { get; } = ApiEndpoints.SignInRewardActivityId;
|
||||
public string ActivityId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 地区代码
|
||||
|
||||
Reference in New Issue
Block a user