Merge pull request #1192 from DGP-Studio/feat/ann

This commit is contained in:
DismissedLight
2023-12-20 16:30:37 +08:00
committed by GitHub
27 changed files with 305 additions and 58 deletions

View File

@@ -127,4 +127,6 @@ internal sealed partial class SettingEntry
/// 自定义极验接口
/// </summary>
public const string GeetestCustomCompositeUrl = "GeetestCustomCompositeUrl";
public const string AnnouncementRegion = "AnnouncementRegion";
}

View File

@@ -2306,6 +2306,12 @@
<data name="ViewPageSettingGeetestVerificationHeader" xml:space="preserve">
<value>无感验证</value>
</data>
<data name="ViewPageSettingHomeAnnouncementRegionDescription" xml:space="preserve">
<value>选择想要获取公告的游戏服务器</value>
</data>
<data name="ViewPageSettingHomeAnnouncementRegionHeader" xml:space="preserve">
<value>公告所属服务器</value>
</data>
<data name="ViewpageSettingHomeCardDescription" xml:space="preserve">
<value>管理主页仪表板中的卡片</value>
</data>
@@ -2852,9 +2858,30 @@
<data name="WebGameResourcePathCopySucceed" xml:space="preserve">
<value>下载链接复制成功</value>
</data>
<data name="WebHoyolabInvalidRegion" xml:space="preserve">
<value>无效的服务器</value>
</data>
<data name="WebHoyolabInvalidUid" xml:space="preserve">
<value>无效的 UID</value>
</data>
<data name="WebHoyolabRegionCNGF01" xml:space="preserve">
<value>国服 官方服</value>
</data>
<data name="WebHoyolabRegionCNQD01" xml:space="preserve">
<value>国服 渠道服</value>
</data>
<data name="WebHoyolabRegionOSASIA" xml:space="preserve">
<value>国际服 亚服</value>
</data>
<data name="WebHoyolabRegionOSCHT" xml:space="preserve">
<value>国际服 台服</value>
</data>
<data name="WebHoyolabRegionOSEURO" xml:space="preserve">
<value>国际服 欧服</value>
</data>
<data name="WebHoyolabRegionOSUSA" xml:space="preserve">
<value>国际服 美服</value>
</data>
<data name="WebHutaoServiceUnAvailable" xml:space="preserve">
<value>胡桃服务维护中</value>
</data>

View File

@@ -1,6 +1,7 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Web.Hoyolab;
using Snap.Hutao.Web.Hoyolab.Hk4e.Common.Announcement;
namespace Snap.Hutao.Service.Abstraction;
@@ -14,7 +15,9 @@ internal interface IAnnouncementService
/// <summary>
/// 异步获取游戏公告与活动,通常会进行缓存
/// </summary>
/// <param name="languageCode">语言代码</param>
/// <param name="region">服务器</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>公告包装器</returns>
ValueTask<AnnouncementWrapper> GetAnnouncementWrapperAsync(CancellationToken cancellationToken = default);
ValueTask<AnnouncementWrapper> GetAnnouncementWrapperAsync(string languageCode, Region region, CancellationToken cancellationToken = default);
}

View File

@@ -3,6 +3,7 @@
using Microsoft.Extensions.Caching.Memory;
using Snap.Hutao.Service.Abstraction;
using Snap.Hutao.Web.Hoyolab;
using Snap.Hutao.Web.Hoyolab.Hk4e.Common.Announcement;
using Snap.Hutao.Web.Response;
using System.Globalization;
@@ -25,17 +26,17 @@ internal sealed partial class AnnouncementService : IAnnouncementService
private readonly IMemoryCache memoryCache;
/// <inheritdoc/>
public async ValueTask<AnnouncementWrapper> GetAnnouncementWrapperAsync(CancellationToken cancellationToken = default)
public async ValueTask<AnnouncementWrapper> GetAnnouncementWrapperAsync(string languageCode, Region region, CancellationToken cancellationToken = default)
{
// 缓存中存在记录,直接返回
if (memoryCache.TryGetRequiredValue(CacheKey, out AnnouncementWrapper? cache))
if (memoryCache.TryGetRequiredValue($"{CacheKey}.{languageCode}.{region}", out AnnouncementWrapper? cache))
{
return cache;
}
await taskContext.SwitchToBackgroundAsync();
Response<AnnouncementWrapper> announcementWrapperResponse = await announcementClient
.GetAnnouncementsAsync(cancellationToken)
.GetAnnouncementsAsync(languageCode, region, cancellationToken)
.ConfigureAwait(false);
if (!announcementWrapperResponse.IsOk())
@@ -45,7 +46,7 @@ internal sealed partial class AnnouncementService : IAnnouncementService
AnnouncementWrapper wrapper = announcementWrapperResponse.Data;
Response<ListWrapper<AnnouncementContent>> announcementContentResponse = await announcementClient
.GetAnnouncementContentsAsync(cancellationToken)
.GetAnnouncementContentsAsync(languageCode, region, cancellationToken)
.ConfigureAwait(false);
if (!announcementContentResponse.IsOk())

View File

@@ -6,6 +6,7 @@ using Snap.Hutao.Core.Windowing;
using Snap.Hutao.Model;
using Snap.Hutao.Model.Entity;
using Snap.Hutao.Service.Abstraction;
using Snap.Hutao.Web.Hoyolab;
using System.Globalization;
using System.IO;
@@ -19,6 +20,7 @@ internal sealed partial class AppOptions : DbStoreOptions
private bool? isEmptyHistoryWishVisible;
private BackdropType? backdropType;
private CultureInfo? currentCulture;
private Region? region;
private string? geetestCustomCompositeUrl;
public string PowerShellPath
@@ -72,6 +74,14 @@ internal sealed partial class AppOptions : DbStoreOptions
set => SetOption(ref currentCulture, SettingEntry.Culture, value, value => value.Name);
}
public List<NameValue<Region>> Regions { get; } = KnownRegions.Get();
public Region Region
{
get => GetOption(ref region, SettingEntry.AnnouncementRegion, v => Region.FromRegionString(v), Region.CNGF01).Value;
set => SetOption(ref region, SettingEntry.AnnouncementRegion, value, value => value.ToStringOrEmpty());
}
public string GeetestCustomCompositeUrl
{
get => GetOption(ref geetestCustomCompositeUrl, SettingEntry.GeetestCustomCompositeUrl);

View File

@@ -2,6 +2,7 @@
// Licensed under the MIT license.
using Snap.Hutao.Model;
using Snap.Hutao.Web.Hoyolab;
using System.Globalization;
namespace Snap.Hutao.Service;
@@ -12,4 +13,9 @@ internal static class AppOptionsExtension
{
return appOptions.Cultures.SingleOrDefault(c => c.Value == appOptions.CurrentCulture);
}
public static NameValue<Region>? GetCurrentRegionForSelectionOrDefault(this AppOptions appOptions)
{
return appOptions.Regions.SingleOrDefault(c => c.Value.Value == appOptions.Region.Value);
}
}

View File

@@ -0,0 +1,23 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Snap.Hutao.Model;
using Snap.Hutao.Web.Hoyolab;
namespace Snap.Hutao.Service;
internal static class KnownRegions
{
public static List<NameValue<Region>> Get()
{
return
[
new(SH.WebHoyolabRegionCNGF01, Region.CNGF01),
new(SH.WebHoyolabRegionCNQD01, Region.CNQD01),
new(SH.WebHoyolabRegionOSUSA, Region.OSUSA),
new(SH.WebHoyolabRegionOSEURO, Region.OSEURO),
new(SH.WebHoyolabRegionOSASIA, Region.OSASIA),
new(SH.WebHoyolabRegionOSCHT, Region.OSCHT),
];
}
}

View File

@@ -13,8 +13,9 @@ internal static class SupportedCultures
ToNameValue(CultureInfo.GetCultureInfo("zh-Hans")),
ToNameValue(CultureInfo.GetCultureInfo("zh-Hant")),
ToNameValue(CultureInfo.GetCultureInfo("en")),
ToNameValue(CultureInfo.GetCultureInfo("ko")),
ToNameValue(CultureInfo.GetCultureInfo("ja")),
ToNameValue(CultureInfo.GetCultureInfo("id")),
ToNameValue(CultureInfo.GetCultureInfo("ko")),
];
public static List<NameValue<CultureInfo>> Get()

View File

@@ -305,6 +305,17 @@
</cwc:SettingsCard>
</cwc:SettingsExpander.Items>
</cwc:SettingsExpander>
<cwc:SettingsCard
Description="{shcm:ResourceString Name=ViewPageSettingHomeAnnouncementRegionDescription}"
Header="{shcm:ResourceString Name=ViewPageSettingHomeAnnouncementRegionHeader}"
HeaderIcon="{shcm:FontIcon Glyph=&#xE8E4;}">
<shc:SizeRestrictedContentControl>
<ComboBox
DisplayMemberPath="Name"
ItemsSource="{Binding AppOptions.Regions}"
SelectedItem="{Binding SelectedRegion, Mode=TwoWay}"/>
</shc:SizeRestrictedContentControl>
</cwc:SettingsCard>
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" Text="{shcm:ResourceString Name=ViewPageSettingGameHeader}"/>
<cwc:SettingsCard

View File

@@ -2,8 +2,10 @@
// Licensed under the MIT license.
using Snap.Hutao.Core.Setting;
using Snap.Hutao.Service;
using Snap.Hutao.Service.Abstraction;
using Snap.Hutao.Service.Hutao;
using Snap.Hutao.Service.Metadata;
using Snap.Hutao.View.Card;
using Snap.Hutao.View.Card.Primitive;
using Snap.Hutao.Web.Hoyolab.Hk4e.Common.Announcement;
@@ -23,6 +25,8 @@ internal sealed partial class AnnouncementViewModel : Abstraction.ViewModel
private readonly IAnnouncementService announcementService;
private readonly HutaoUserOptions hutaoUserOptions;
private readonly ITaskContext taskContext;
private readonly MetadataOptions metadataOptions;
private readonly AppOptions appOptions;
private AnnouncementWrapper? announcement;
private string greetingText = SH.ViewPageHomeGreetingTextDefault;
@@ -61,7 +65,7 @@ internal sealed partial class AnnouncementViewModel : Abstraction.ViewModel
{
try
{
AnnouncementWrapper announcementWrapper = await announcementService.GetAnnouncementWrapperAsync(CancellationToken).ConfigureAwait(false);
AnnouncementWrapper announcementWrapper = await announcementService.GetAnnouncementWrapperAsync(metadataOptions.LanguageCode, appOptions.Region, CancellationToken).ConfigureAwait(false);
await taskContext.SwitchToMainThreadAsync();
Announcement = announcementWrapper;
}
@@ -138,4 +142,4 @@ internal sealed partial class AnnouncementViewModel : Abstraction.ViewModel
Cards = result;
}
}
}

View File

@@ -23,6 +23,7 @@ using Snap.Hutao.Service.Notification;
using Snap.Hutao.Service.User;
using Snap.Hutao.View.Dialog;
using Snap.Hutao.ViewModel.Guide;
using Snap.Hutao.Web.Hoyolab;
using Snap.Hutao.Web.Hutao;
using Snap.Hutao.Web.Response;
using System.Globalization;
@@ -61,6 +62,7 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
private NameValue<BackdropType>? selectedBackdropType;
private NameValue<CultureInfo>? selectedCulture;
private NameValue<Region>? selectedRegion;
private IPInformation? ipInformation;
private FolderViewModel? cacheFolderView;
private FolderViewModel? dataFolderView;
@@ -104,6 +106,18 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
}
}
public NameValue<Region>? SelectedRegion
{
get => selectedRegion ??= AppOptions.GetCurrentRegionForSelectionOrDefault();
set
{
if (SetProperty(ref selectedRegion, value) && value is not null)
{
AppOptions.Region = value.Value;
}
}
}
public FolderViewModel? CacheFolderView { get => cacheFolderView; set => SetProperty(ref cacheFolderView, value); }
public FolderViewModel? DataFolderView { get => dataFolderView; set => SetProperty(ref dataFolderView, value); }

View File

@@ -281,12 +281,24 @@ internal static class ApiEndpoints
/// <summary>
/// 公告列表
/// </summary>
public const string AnnList = $"{Hk4eApiAnnouncementApi}/getAnnList?{AnnouncementQuery}";
/// <param name="languageCode">语言代码</param>
/// <param name="region">服务器</param>
/// <returns>公告列表Url</returns>
public static string AnnList(string languageCode, in Region region)
{
return $"{Hk4eApiAnnouncementApi}/getAnnList?{AnnouncementQuery(languageCode, region)}";
}
/// <summary>
/// 公告内容
/// </summary>
public const string AnnContent = $"{Hk4eApiAnnouncementApi}/getAnnContent?{AnnouncementQuery}";
/// <param name="languageCode">语言代码</param>
/// <param name="region">服务器</param>
/// <returns>公告列表Url</returns>
public static string AnnContent(string languageCode, in Region region)
{
return $"{Hk4eApiAnnouncementApi}/getAnnContent?{AnnouncementQuery(languageCode, region)}";
}
#endregion
#region Hk4eSdk
@@ -422,6 +434,9 @@ internal static class ApiEndpoints
/// </summary>
public const string WebStaticMihoyoReferer = "https://webstatic.mihoyo.com";
private const string AnnouncementQuery = "game=hk4e&game_biz=hk4e_cn&lang=zh-cn&bundle_id=hk4e_cn&platform=pc&region=cn_gf01&level=55&uid=100000000";
private static string AnnouncementQuery(string languageCode, in Region region)
{
return $"game=hk4e&game_biz=hk4e_cn&lang={languageCode}&bundle_id=hk4e_cn&platform=pc&region={region}&level=55&uid=100000000";
}
#endregion
}

View File

@@ -100,7 +100,7 @@ internal static class ApiOsEndpoints
/// </summary>
/// <param name="region">地区代号</param>
/// <returns>用户游戏角色字符串</returns>
public static string UserGameRolesByLtoken(string region)
public static string UserGameRolesByLtoken(in Region region)
{
return $"{ApiAccountOsBindingApi}/getUserGameRolesByLtoken?game_biz=hk4e_global&region={region}";
}
@@ -189,6 +189,32 @@ internal static class ApiOsEndpoints
}
#endregion
#region Hk4eApiOsAnnouncementApi
/// <summary>
/// 公告列表
/// </summary>
/// <param name="languageCode">语言代码</param>
/// <param name="region">服务器</param>
/// <returns>公告列表Url</returns>
public static string AnnList(string languageCode, in Region region)
{
return $"{Hk4eApiOsAnnouncementApi}/getAnnList?{AnnouncementQuery(languageCode, region)}";
}
/// <summary>
/// 公告内容
/// </summary>
/// <param name="languageCode">语言代码</param>
/// <param name="region">服务器</param>
/// <returns>公告内容Url</returns>
public static string AnnContent(string languageCode, in Region region)
{
return $"{Hk4eApiOsAnnouncementApi}/getAnnContent?{AnnouncementQuery(languageCode, region)}";
}
#endregion
#region SgPublicApi
/// <summary>
@@ -307,6 +333,7 @@ internal static class ApiOsEndpoints
private const string BbsApiOsGameRecordAppApi = $"{BbsApiOs}/game_record/app/genshin/api";
private const string Hk4eApiOs = "https://hk4e-api-os.hoyoverse.com";
private const string Hk4eApiOsAnnouncementApi = $"{Hk4eApiOs}/common/hk4e_global/announcement/api";
private const string Hk4eApiOsGachaInfoApi = $"{Hk4eApiOs}/gacha_info/api";
private const string SdkOsStatic = "https://sdk-os-static.mihoyo.com";
@@ -333,5 +360,10 @@ internal static class ApiOsEndpoints
/// </summary>
public const string AppHoyolabReferer = "https://app.hoyolab.com/";
private static string AnnouncementQuery(string languageCode, in Region region)
{
return $"game=hk4e&game_biz=hk4e_global&lang={languageCode}&bundle_id=hk4e_global&platform=pc&region={region}&level=55&uid=100000000";
}
#endregion
}

View File

@@ -23,12 +23,18 @@ internal sealed partial class AnnouncementClient
/// <summary>
/// 异步获取公告列表
/// </summary>
/// <param name="languageCode">语言代码</param>
/// <param name="region">服务器</param>
/// <param name="token">取消令牌</param>
/// <returns>公告列表</returns>
public async ValueTask<Response<AnnouncementWrapper>> GetAnnouncementsAsync(CancellationToken token = default)
public async ValueTask<Response<AnnouncementWrapper>> GetAnnouncementsAsync(string languageCode, Region region, CancellationToken token = default)
{
string annListUrl = region.IsOversea()
? ApiOsEndpoints.AnnList(languageCode, region)
: ApiEndpoints.AnnList(languageCode, region);
HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create()
.SetRequestUri(ApiEndpoints.AnnList)
.SetRequestUri(annListUrl)
.Get();
Response<AnnouncementWrapper>? resp = await builder
@@ -41,12 +47,18 @@ internal sealed partial class AnnouncementClient
/// <summary>
/// 异步获取公告内容列表
/// </summary>
/// <param name="languageCode">语言代码</param>
/// <param name="region">服务器</param>
/// <param name="token">取消令牌</param>
/// <returns>公告内容列表</returns>
public async ValueTask<Response<ListWrapper<AnnouncementContent>>> GetAnnouncementContentsAsync(CancellationToken token = default)
public async ValueTask<Response<ListWrapper<AnnouncementContent>>> GetAnnouncementContentsAsync(string languageCode, Region region, CancellationToken token = default)
{
string annContentUrl = region.IsOversea()
? ApiOsEndpoints.AnnContent(languageCode, region)
: ApiEndpoints.AnnContent(languageCode, region);
HttpRequestMessageBuilder builder = httpRequestMessageBuilderFactory.Create()
.SetRequestUri(ApiEndpoints.AnnContent)
.SetRequestUri(annContentUrl)
.Get();
Response<ListWrapper<AnnouncementContent>>? resp = await builder

View File

@@ -41,7 +41,8 @@ internal sealed class GachaLogPage : IJsonOnDeserialized
/// 地区
/// </summary>
[JsonPropertyName("region")]
public string Region { get; set; } = default!;
[JsonConverter(typeof(RegionConverter))]
public Region Region { get; set; } = default!;
public void OnDeserialized()
{

View File

@@ -0,0 +1,15 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using System.Text.RegularExpressions;
namespace Snap.Hutao.Web.Hoyolab;
internal static partial class HoyolabRegex
{
[GeneratedRegex("^[1-9][0-9]{8}$")]
public static partial Regex UidRegex();
[GeneratedRegex("^(cn_gf01|cn_qd01|os_usa|os_euro|os_asia|os_cht)$")]
public static partial Regex RegionRegex();
}

View File

@@ -1,8 +1,6 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using System.Text.RegularExpressions;
namespace Snap.Hutao.Web.Hoyolab;
/// <summary>
@@ -19,18 +17,18 @@ internal readonly partial struct PlayerUid
/// <summary>
/// 地区代码
/// </summary>
public readonly string Region;
public readonly Region Region;
/// <summary>
/// 构造一个新的玩家 Uid 结构
/// </summary>
/// <param name="value">uid</param>
/// <param name="region">服务器,当提供该参数时会无条件信任</param>
public PlayerUid(string value, string? region = default)
public PlayerUid(string value, in Region? region = default)
{
Must.Argument(UidRegex().IsMatch(value), SH.WebHoyolabInvalidUid);
Must.Argument(HoyolabRegex.UidRegex().IsMatch(value), SH.WebHoyolabInvalidUid);
Value = value;
Region = region ?? EvaluateRegion(value.AsSpan()[0]);
Region = region ?? Region.FromUidString(value);
}
public static implicit operator PlayerUid(string source)
@@ -45,7 +43,7 @@ internal readonly partial struct PlayerUid
public static bool IsOversea(string uid)
{
Must.Argument(UidRegex().IsMatch(uid), SH.WebHoyolabInvalidUid);
Must.Argument(HoyolabRegex.UidRegex().IsMatch(uid), SH.WebHoyolabInvalidUid);
return uid.AsSpan()[0] switch
{
@@ -56,7 +54,7 @@ internal readonly partial struct PlayerUid
public static TimeSpan GetRegionTimeZoneUtcOffsetForUid(string uid)
{
Must.Argument(UidRegex().IsMatch(uid), SH.WebHoyolabInvalidUid);
Must.Argument(HoyolabRegex.UidRegex().IsMatch(uid), SH.WebHoyolabInvalidUid);
// 美服 UTC-05
// 欧服 UTC+01
@@ -69,12 +67,12 @@ internal readonly partial struct PlayerUid
};
}
public static TimeSpan GetRegionTimeZoneUtcOffsetForRegion(string region)
public static TimeSpan GetRegionTimeZoneUtcOffsetForRegion(in Region region)
{
// 美服 UTC-05
// 欧服 UTC+01
// 其他 UTC+08
return region switch
return region.Value switch
{
"os_usa" => ServerRegionTimeZone.AmericaServerOffset,
"os_euro" => ServerRegionTimeZone.EuropeServerOffset,
@@ -87,24 +85,4 @@ internal readonly partial struct PlayerUid
{
return Value;
}
private static string EvaluateRegion(in char first)
{
return first switch
{
// CN
>= '1' and <= '4' => "cn_gf01", // 国服
'5' => "cn_qd01", // 渠道
// OS
'6' => "os_usa", // 美服
'7' => "os_euro", // 欧服
'8' => "os_asia", // 亚服
'9' => "os_cht", // 台服
_ => throw Must.NeverHappen(),
};
}
[GeneratedRegex("^[1-9][0-9]{8}$")]
private static partial Regex UidRegex();
}

View File

@@ -12,7 +12,7 @@ internal static class PlayerUidExtension
{
NameValueCollection collection = [];
collection.Set("role_id", playerUid.Value);
collection.Set("server", playerUid.Region);
collection.Set("server", playerUid.Region.Value);
return collection.ToQueryString();
}
@@ -21,7 +21,7 @@ internal static class PlayerUidExtension
{
NameValueCollection collection = [];
collection.Set("uid", playerUid.Value);
collection.Set("region", playerUid.Region);
collection.Set("region", playerUid.Region.Value);
return collection.ToQueryString();
}

View File

@@ -0,0 +1,70 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Web.Hoyolab;
[JsonConverter(typeof(RegionConverter))]
internal readonly partial struct Region
{
public static readonly Region CNGF01 = new("cn_gf01");
public static readonly Region CNQD01 = new("cn_qd01");
public static readonly Region OSUSA = new("os_usa");
public static readonly Region OSEURO = new("os_euro");
public static readonly Region OSASIA = new("os_asia");
public static readonly Region OSCHT = new("os_cht");
public readonly string Value;
public Region(string value)
{
Must.Argument(HoyolabRegex.RegionRegex().IsMatch(value), SH.WebHoyolabInvalidRegion);
Value = value;
}
public static implicit operator Region(string value)
{
return FromRegionString(value);
}
public static Region FromRegionString(string value)
{
return new(value);
}
public static Region FromUidString(string uid)
{
return uid.AsSpan()[0] switch
{
// CN
>= '1' and <= '4' => new("cn_gf01"), // 国服
'5' => new("cn_qd01"), // 渠道
// OS
'6' => new("os_usa"), // 美服
'7' => new("os_euro"), // 欧服
'8' => new("os_asia"), // 亚服
'9' => new("os_cht"), // 台服
_ => throw Must.NeverHappen(),
};
}
public static bool IsOversea(string value)
{
Must.Argument(HoyolabRegex.RegionRegex().IsMatch(value), SH.WebHoyolabInvalidRegion);
return value.AsSpan()[..2] switch
{
"os" => true,
_ => false,
};
}
public readonly bool IsOversea()
{
return IsOversea(Value);
}
public override string ToString()
{
return Value;
}
}

View File

@@ -0,0 +1,22 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Web.Hoyolab;
internal sealed class RegionConverter : JsonConverter<Region>
{
public override Region Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.GetString() is { } regionValue)
{
return Region.FromRegionString(regionValue);
}
throw new JsonException();
}
public override void Write(Utf8JsonWriter writer, Region value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.Value);
}
}

View File

@@ -50,7 +50,7 @@ internal sealed class GenAuthKeyData
/// 区域
/// </summary>
[JsonPropertyName("region")]
public string Region { get; set; } = default!;
public Region Region { get; set; } = default!;
/// <summary>
/// 创建为祈愿记录验证密钥提交数据

View File

@@ -19,7 +19,7 @@ internal sealed class UserGameRole
/// 服务器
/// </summary>
[JsonPropertyName("region")]
public string Region { get; set; } = default!;
public Region Region { get; set; } = default!;
/// <summary>
/// 游戏Uid

View File

@@ -31,7 +31,7 @@ internal sealed class SignInData
/// 地区代码
/// </summary>
[JsonPropertyName("region")]
public string Region { get; }
public Region Region { get; }
/// <summary>
/// Uid

View File

@@ -181,7 +181,7 @@ internal sealed partial class CalculateClient
public string Uid { get; set; } = default!;
[JsonPropertyName("region")]
public string Region { get; set; } = default!;
public Region Region { get; set; } = default!;
}
private class IdCount

View File

@@ -39,5 +39,5 @@ internal sealed class CharacterData
/// 服务器
/// </summary>
[JsonPropertyName("server")]
public string Server { get; }
public Region Server { get; }
}

View File

@@ -22,10 +22,10 @@ internal sealed class Role
public string Nickname { get; set; } = default!;
/// <summary>
/// 服务器
/// 服务器名称
/// </summary>
[JsonPropertyName("region")]
public string Region { get; set; } = default!;
public string RegionName { get; set; } = default!;
/// <summary>
/// 等级

View File

@@ -23,10 +23,10 @@ internal sealed class BasicRoleInfo
public string Nickname { get; set; } = default!;
/// <summary>
/// 区域代码
/// 服务器名称
/// </summary>
[JsonPropertyName("region")]
public string Region { get; set; } = default!;
public string RegionName { get; set; } = default!;
/// <summary>
/// 等级