add sophon support

This commit is contained in:
qhy040404
2024-07-15 23:00:29 +08:00
parent a8065bf6e6
commit 97a0b0b4d7
15 changed files with 287 additions and 2 deletions

View File

@@ -4,6 +4,7 @@
using Snap.Hutao.Model.Primitive;
using Snap.Hutao.Service.Game.Scheme;
using Snap.Hutao.Web.Hoyolab;
using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.Branch;
namespace Snap.Hutao.Web;
@@ -157,6 +158,15 @@ internal static class ApiEndpoints
public const string GameRecordRoleCombatPath = $"{ApiTakumiRecordApi}/role_combat";
#endregion
#region ApiTakumiDownloaderApi
public static string SophonChunkGetBuild(BranchWrapper branch)
{
return $"{ApiTakumiDownloaderApi}/sophon_chunk/getBuild?branch={branch.Branch}&package_id={branch.PackageId}&password={branch.Password}";
}
#endregion
#region ApiTakumiEventCalculate
#region V1
@@ -307,6 +317,11 @@ internal static class ApiEndpoints
return $"{HoyoPlayApiConnectApi}/getGameDeprecatedFileConfigs?channel={scheme.Channel:D}&game_ids[]={scheme.GameId}&launcher_id={scheme.LauncherId}&sub_channel={scheme.SubChannel:D}";
}
public static string HoyoPlayConnectGameBranches(LaunchScheme scheme)
{
return $"{HoyoPlayApiConnectApi}/getGameBranches?game_ids[]={scheme.GameId}&launcher_id={scheme.LauncherId}";
}
#endregion
#region PassportApi | PassportApiV4
@@ -381,6 +396,8 @@ internal static class ApiEndpoints
private const string ApiTakumiCardApi = $"{ApiTakumiRecord}/game_record/app/card/api";
private const string ApiTakumiCardWApi = $"{ApiTakumiRecord}/game_record/app/card/wapi";
private const string ApiTakumiDownloaderApi = $"{ApiTakumi}/downloader";
private const string ApiTakumiEvent = $"{ApiTakumi}/event";
private const string ApiTakumiEventCalculate = $"{ApiTakumiEvent}/e20200928calculate";
private const string ApiTakumiEventLuna = $"{ApiTakumiEvent}/luna";
@@ -423,4 +440,4 @@ internal static class ApiEndpoints
return $"game=hk4e&game_biz=hk4e_cn&lang={languageCode}&bundle_id=hk4e_cn&platform=pc&region={region}&level=55&uid=100000000";
}
#endregion
}
}

View File

@@ -4,6 +4,7 @@
using Snap.Hutao.Model.Primitive;
using Snap.Hutao.Service.Game.Scheme;
using Snap.Hutao.Web.Hoyolab;
using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.Branch;
namespace Snap.Hutao.Web;
@@ -254,6 +255,11 @@ internal static class ApiOsEndpoints
/// </summary>
public const string CalculateSyncAvatarList = $"{SgPublicApi}/event/calculateos/sync/avatar/list";
public static string SophonChunkGetBuild(BranchWrapper branch)
{
return $"{SgPublicApi}/sophon_chunk/getBuild?branch={branch.Branch}&package_id={branch.PackageId}&password={branch.Password}";
}
#endregion
#region SgHk4eApi
@@ -316,6 +322,11 @@ internal static class ApiOsEndpoints
return $"{SgHoyoPlayApiConnectApi}/getGameDeprecatedFileConfigs?channel={scheme.Channel:D}&game_ids[]={scheme.GameId}&launcher_id={scheme.LauncherId}&sub_channel={scheme.SubChannel:D}";
}
public static string HoyoPlayConnectGameBranches(LaunchScheme scheme)
{
return $"{SgHoyoPlayApiConnectApi}/getGameBranches?game_ids[]={scheme.GameId}&launcher_id={scheme.LauncherId}";
}
#endregion
#region WebApiOsAccountApi
@@ -373,4 +384,4 @@ internal static class ApiOsEndpoints
}
#endregion
}
}

View File

@@ -0,0 +1,19 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.Branch;
internal sealed class BranchWrapper
{
[JsonPropertyName("package_id")]
public string PackageId { get; set; } = default!;
[JsonPropertyName("branch")]
public string Branch { get; set; } = default!;
[JsonPropertyName("password")]
public string Password { get; set; } = default!;
[JsonPropertyName("tag")]
public string Tag { get; set; } = default!;
}

View File

@@ -0,0 +1,13 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.Branch;
internal sealed class GameBranch : GameIndexedObject
{
[JsonPropertyName("main")]
public BranchWrapper Main { get; set; } = default!;
[JsonPropertyName("pre_download")]
public BranchWrapper PreDownload { get; set; } = default!;
}

View File

@@ -0,0 +1,10 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.Branch;
internal sealed class GameBranchesWrapper
{
[JsonPropertyName("game_branches")]
public List<GameBranch> GameBranches { get; set; } = default!;
}

View File

@@ -3,6 +3,7 @@
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
using Snap.Hutao.Service.Game.Scheme;
using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.Branch;
using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.ChannelSDK;
using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.DeprecatedFile;
using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.Package;
@@ -71,4 +72,21 @@ internal sealed partial class HoyoPlayClient
return Response.Response.DefaultIfNull(resp);
}
public async ValueTask<Response<GameBranchesWrapper>> GetBranchesAsync(LaunchScheme scheme, CancellationToken token = default)
{
string url = scheme.IsOversea
? ApiOsEndpoints.HoyoPlayConnectGameBranches(scheme)
: ApiEndpoints.HoyoPlayConnectGameBranches(scheme);
HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create()
.SetRequestUri(url)
.Get();
Response<GameBranchesWrapper>? resp = await builder
.SendAsync<Response<GameBranchesWrapper>>(httpClient, logger, token)
.ConfigureAwait(false);
return Response.Response.DefaultIfNull(resp);
}
}

View File

@@ -0,0 +1,12 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.Branch;
using Snap.Hutao.Web.Response;
namespace Snap.Hutao.Web.Hoyolab.Takumi.Downloader;
internal interface ISophonClient
{
ValueTask<Response<SophonBuild>> GetBuildAsync(BranchWrapper branch, CancellationToken token = default);
}

View File

@@ -0,0 +1,19 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Web.Hoyolab.Takumi.Downloader;
internal sealed class Manifest
{
[JsonPropertyName("id")]
public string Id { get; set; } = default!;
[JsonPropertyName("checksum")]
public string Checksum { get; set; } = default!;
[JsonPropertyName("compressed_size")]
public string CompressedSize { get; set; } = default!;
[JsonPropertyName("uncompressed_size")]
public string UncompressedSize { get; set; } = default!;
}

View File

@@ -0,0 +1,22 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Web.Hoyolab.Takumi.Downloader;
internal sealed class ManifestDownloadInfo
{
[JsonPropertyName("encryption")]
public uint Encryption { get; set; }
[JsonPropertyName("password")]
public string Password { get; set; } = default!;
[JsonPropertyName("compression")]
public uint Compression { get; set; }
[JsonPropertyName("url_prefix")]
public string UrlPrefix { get; set; } = default!;
[JsonPropertyName("url_suffix")]
public string UrlSuffix { get; set; } = default!;
}

View File

@@ -0,0 +1,19 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Web.Hoyolab.Takumi.Downloader;
internal sealed class ManifestStats
{
[JsonPropertyName("compressed_size")]
public string CompressedSize { get; set; } = default!;
[JsonPropertyName("uncompressed_size")]
public string UncompressedSize { get; set; } = default!;
[JsonPropertyName("file_count")]
public string FileCount { get; set; } = default!;
[JsonPropertyName("chunk_count")]
public string ChunkCount { get; set; } = default!;
}

View File

@@ -0,0 +1,16 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Web.Hoyolab.Takumi.Downloader;
internal sealed class SophonBuild
{
[JsonPropertyName("build_id")]
public string BuildId { get; set; } = default!;
[JsonPropertyName("tag")]
public string Tag { get; set; } = default!;
[JsonPropertyName("manifests")]
public List<SophonManifest> Manifests { get; set; } = default!;
}

View File

@@ -0,0 +1,33 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.Branch;
using Snap.Hutao.Web.Request.Builder;
using Snap.Hutao.Web.Request.Builder.Abstraction;
using Snap.Hutao.Web.Response;
using System.Net.Http;
namespace Snap.Hutao.Web.Hoyolab.Takumi.Downloader;
[ConstructorGenerated(ResolveHttpClient = true)]
[HttpClient(HttpClientConfiguration.Default)]
internal sealed partial class SophonClient : ISophonClient
{
private readonly IHttpRequestMessageBuilderFactory httpRequestMessageBuilderFactory;
private readonly ILogger<SophonClient> logger;
private readonly HttpClient httpClient;
public async ValueTask<Response<SophonBuild>> GetBuildAsync(BranchWrapper branch, CancellationToken token = default)
{
HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create()
.SetRequestUri(ApiEndpoints.SophonChunkGetBuild(branch))
.Get();
Response<SophonBuild>? resp = await builder
.SendAsync<Response<SophonBuild>>(httpClient, logger, token)
.ConfigureAwait(false);
return Response.Response.DefaultIfNull(resp);
}
}

View File

@@ -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.Downloader;
[Injection(InjectAs.Transient, typeof(IOverseaSupportFactory<ISophonClient>))]
[ConstructorGenerated(CallBaseConstructor = true)]
internal sealed partial class SophonClientFactory : OverseaSupportFactory<ISophonClient, SophonClient, SophonClientOversea>
{
}

View File

@@ -0,0 +1,33 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
using Snap.Hutao.Web.Hoyolab.HoyoPlay.Connect.Branch;
using Snap.Hutao.Web.Request.Builder;
using Snap.Hutao.Web.Request.Builder.Abstraction;
using Snap.Hutao.Web.Response;
using System.Net.Http;
namespace Snap.Hutao.Web.Hoyolab.Takumi.Downloader;
[ConstructorGenerated(ResolveHttpClient = true)]
[HttpClient(HttpClientConfiguration.Default)]
internal sealed partial class SophonClientOversea : ISophonClient
{
private readonly IHttpRequestMessageBuilderFactory httpRequestMessageBuilderFactory;
private readonly ILogger<SophonClientOversea> logger;
private readonly HttpClient httpClient;
public async ValueTask<Response<SophonBuild>> GetBuildAsync(BranchWrapper branch, CancellationToken token = default)
{
HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create()
.SetRequestUri(ApiOsEndpoints.SophonChunkGetBuild(branch))
.Get();
Response<SophonBuild>? resp = await builder
.SendAsync<Response<SophonBuild>>(httpClient, logger, token)
.ConfigureAwait(false);
return Response.Response.DefaultIfNull(resp);
}
}

View File

@@ -0,0 +1,31 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Web.Hoyolab.Takumi.Downloader;
internal sealed class SophonManifest
{
[JsonPropertyName("category_id")]
public string CategoryId { get; set; } = default!;
[JsonPropertyName("category_name")]
public string CategoryName { get; set; } = default!;
[JsonPropertyName("manifest")]
public Manifest Manifest { get; set; } = default!;
[JsonPropertyName("chunk_download")]
public ManifestDownloadInfo ChunkDownload { get; set; } = default!;
[JsonPropertyName("manifest_download")]
public ManifestDownloadInfo ManifestDownload { get; set; } = default!;
[JsonPropertyName("matching_field")]
public string MatchingField { get; set; } = default!;
[JsonPropertyName("stats")]
public ManifestStats Stats { get; set; } = default!;
[JsonPropertyName("deduplicated_stats")]
public ManifestStats DeduplicatedStats { get; set; } = default!;
}