Hutao GachaEvent Statistics 1

This commit is contained in:
Lightczx
2023-07-10 09:31:16 +08:00
parent 133a1a532e
commit 173a1343c1
22 changed files with 136 additions and 25 deletions

View File

@@ -81,7 +81,7 @@ internal static partial class EnumerableExtension
/// <param name="collection">Collection to convert. Cannot be <see langword="null"/>.</param>
/// <param name="separator">Delimiter between elements in the final string.</param>
/// <returns>Converted collection into string.</returns>
public static string ToString<T>(this IEnumerable<T> collection, char separator = ',')
public static string ToString<T>(this IEnumerable<T> collection, char separator)
{
string result = string.Join(separator, collection);
return result.Length > 0 ? result : string.Empty;
@@ -95,7 +95,7 @@ internal static partial class EnumerableExtension
/// <param name="separator">Delimiter between elements in the final string.</param>
/// <param name="defaultValue">A string to be returned if collection has no elements.</param>
/// <returns>Converted collection into string.</returns>
public static string ToString<T>(this IEnumerable<T> collection, char separator = ',', string defaultValue = "")
public static string ToString<T>(this IEnumerable<T> collection, char separator, string defaultValue)
{
string result = string.Join(separator, collection);
return result.Length > 0 ? result : defaultValue;

View File

@@ -25,7 +25,7 @@ public static partial class Program
[STAThread]
private static void Main(string[] args)
{
System.Diagnostics.Debug.WriteLine($"[Arguments]:[{EnumerableExtension.ToString(args)}]");
System.Diagnostics.Debug.WriteLine($"[Arguments]:[{args.ToString(',')}]");
XamlCheckProcessRequirements();
ComWrappersSupport.InitializeComWrappers();

View File

@@ -65,7 +65,7 @@ internal sealed partial class AnnouncementService : IAnnouncementService
private static void JoinAnnouncements(Dictionary<int, string> contentMap, List<AnnouncementListWrapper> announcementListWrappers)
{
Regex timeTagRegrex = XmlTagRegex();
Regex timeTagRegex = XmlTagRegex();
foreach (ref AnnouncementListWrapper listWrapper in CollectionsMarshal.AsSpan(announcementListWrappers))
{
@@ -74,7 +74,7 @@ internal sealed partial class AnnouncementService : IAnnouncementService
if (contentMap.TryGetValue(item.AnnId, out string? rawContent))
{
// remove <t/> tag
rawContent = timeTagRegrex.Replace(rawContent!, x => x.Groups[1].Value);
rawContent = timeTagRegex.Replace(rawContent, x => x.Groups[1].Value);
}
item.Content = rawContent ?? string.Empty;

View File

@@ -21,7 +21,7 @@ internal static class GachaLogQueryProviderExtension
string? name = option switch
{
RefreshOption.WebCache => nameof(GachaLogQueryWebCacheProvider),
RefreshOption.SToken => nameof(GachaLogQuerySToken2Provider),
RefreshOption.SToken => nameof(GachaLogQuerySTokenProvider),
RefreshOption.ManualInput => nameof(GachaLogQueryManualInputProvider),
_ => null,
};

View File

@@ -15,13 +15,13 @@ namespace Snap.Hutao.Service.GachaLog.QueryProvider;
[HighQuality]
[ConstructorGenerated]
[Injection(InjectAs.Transient, typeof(IGachaLogQueryProvider))]
internal sealed partial class GachaLogQuerySToken2Provider : IGachaLogQueryProvider
internal sealed partial class GachaLogQuerySTokenProvider : IGachaLogQueryProvider
{
private readonly BindingClient2 bindingClient2;
private readonly IUserService userService;
/// <inheritdoc/>
public string Name { get => nameof(GachaLogQuerySToken2Provider); }
public string Name { get => nameof(GachaLogQuerySTokenProvider); }
/// <inheritdoc/>
public async Task<ValueResult<bool, GachaLogQuery>> GetQueryAsync()

View File

@@ -36,7 +36,7 @@ internal sealed partial class RegistryLauncherLocator : IGameLocator
{
string? path = Path.GetDirectoryName(result.Value);
string configPath = Path.Combine(path!, GameConstants.ConfigFileName);
string? escapedPath = null;
string? escapedPath;
using (FileStream stream = File.OpenRead(configPath))
{
IEnumerable<IniElement> elements = IniSerializer.Deserialize(stream);
@@ -79,7 +79,7 @@ internal sealed partial class RegistryLauncherLocator : IGameLocator
private static string Unescape(string str)
{
string? hex4Result = UTF16Regex().Replace(str, @"\u$1");
string hex4Result = UTF16Regex().Replace(str, @"\u$1");
// 不包含中文
// Some one's folder might begin with 'u'

View File

@@ -320,7 +320,7 @@ internal sealed partial class PackageConverter
Dictionary<string, VersionItem> results = new();
using (StreamReader reader = new(stream))
{
while (await reader.ReadLineAsync().ConfigureAwait(false) is string raw)
while (await reader.ReadLineAsync().ConfigureAwait(false) is { } raw)
{
if (string.IsNullOrEmpty(raw))
{
@@ -341,7 +341,7 @@ internal sealed partial class PackageConverter
using (StreamReader reader = new(stream))
{
while (await reader.ReadLineAsync().ConfigureAwait(false) is string raw)
while (await reader.ReadLineAsync().ConfigureAwait(false) is { } raw)
{
if (string.IsNullOrEmpty(raw))
{

View File

@@ -85,6 +85,7 @@ internal sealed class HutaoUserOptions : ObservableObject, IOptions<HutaoUserOpt
public void UpdateUserInfo(UserInfo userInfo)
{
IsLicensedDeveloper = userInfo.IsLicensedDeveloper;
IsCloudServiceAllowed = userInfo.GachaLogExpireAt > DateTimeOffset.Now;
GachaLogExpireAt = string.Format(SH.ServiceHutaoUserGachaLogExpiredAt, userInfo.GachaLogExpireAt);
}
}

View File

@@ -97,7 +97,7 @@ internal sealed partial class MetadataOptions : IOptions<MetadataOptions>
while (true)
{
if (cultureInfo == CultureInfo.InvariantCulture)
if (Equals(cultureInfo, CultureInfo.InvariantCulture))
{
// Fallback to Chinese.
return "CHS";

View File

@@ -144,7 +144,7 @@ internal sealed partial class MetadataService : IMetadataService, IMetadataServi
{
using (StreamWriter streamWriter = File.CreateText(metadataOptions.GetLocalizedLocalFile(fileFullName)))
{
while (await streamReader.ReadLineAsync(token).ConfigureAwait(false) is string line)
while (await streamReader.ReadLineAsync(token).ConfigureAwait(false) is { } line)
{
await streamWriter.WriteAsync(line).ConfigureAwait(false);
@@ -182,7 +182,7 @@ internal sealed partial class MetadataService : IMetadataService, IMetadataServi
else
{
FileNotFoundException exception = new(SH.ServiceMetadataFileNotFound, fileName);
throw ThrowHelper.UserdataCorrupted(SH.ServiceMetadataFileNotFound, null!);
throw ThrowHelper.UserdataCorrupted(SH.ServiceMetadataFileNotFound, exception);
}
}

View File

@@ -203,7 +203,7 @@ internal sealed partial class NavigationService : INavigationService, INavigatio
private void OnBackRequested(NavigationView sender, NavigationViewBackRequestedEventArgs args)
{
if (frame != null && frame.CanGoBack)
if (frame is { CanGoBack: true })
{
frame.GoBack();
SyncSelectedNavigationViewItemWith(frame.Content.GetType());

View File

@@ -27,4 +27,25 @@ internal sealed class GachaStatisticsSlim
/// 奔行世间
/// </summary>
public TypedWishSummarySlim StandardWish { get; set; } = default!;
}
/// <summary>
/// 简化的祈愿统计
/// </summary>
internal sealed class HutaoStatistics
{
/// <summary>
/// 角色活动
/// </summary>
public TypedWishSummarySlim AvatarEvent { get; set; } = default!;
/// <summary>
/// 角色活动2
/// </summary>
public TypedWishSummarySlim AvatarEvent2 { get; set; } = default!;
/// <summary>
/// 神铸赋形
/// </summary>
public TypedWishSummarySlim WeaponWish { get; set; } = default!;
}

View File

@@ -0,0 +1,16 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.ViewModel.GachaLog;
/// <summary>
/// 胡桃云服务统计视图模型
/// </summary>
[ConstructorGenerated]
[Injection(InjectAs.Scoped)]
internal sealed partial class HutaoCloudStatisticsViewModel
{
}
public

View File

@@ -130,12 +130,15 @@ internal sealed partial class HutaoCloudViewModel : Abstraction.ViewModel
private async Task RefreshUidCollectionAsync()
{
Response<List<string>> resp = await hutaoCloudService.GetUidsAsync().ConfigureAwait(false);
await taskContext.SwitchToMainThreadAsync();
if (Options.IsCloudServiceAllowed = resp.IsOk())
if (Options.IsCloudServiceAllowed)
{
Uids = resp.Data!.ToObservableCollection();
Response<List<string>> resp = await hutaoCloudService.GetUidsAsync().ConfigureAwait(false);
await taskContext.SwitchToMainThreadAsync();
if (resp.IsOk())
{
Uids = resp.Data!.ToObservableCollection();
}
}
}
}

View File

@@ -0,0 +1,9 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.ViewModel.GachaLog;
internal sealed class HutaoWishSummary
{
public GachaEvent
}

View File

@@ -72,7 +72,7 @@ internal class MiHoYoJSInterface
User user = serviceProvider.GetRequiredService<IUserService>().Current!;
return await serviceProvider
.GetRequiredService<AuthClient>()
.GetActionTicketBySTokenAsync(jsParam.Payload!.ActionType, user.Entity)
.GetActionTicketBySTokenAsync(jsParam.Payload.ActionType, user.Entity)
.ConfigureAwait(false);
}
@@ -200,7 +200,7 @@ internal class MiHoYoJSInterface
{
IUserService userService = serviceProvider.GetRequiredService<IUserService>();
User user = userService.Current!;
if (param.Payload!.ForceRefresh)
if (param.Payload.ForceRefresh)
{
await userService.RefreshCookieTokenAsync(user).ConfigureAwait(false);
}

View File

@@ -9,7 +9,6 @@ namespace Snap.Hutao.Web.Hoyolab.Annotation;
/// API 信息
/// 指示此API 已经经过验证,且明确其调用
/// </summary>
/// <typeparam name="TReturnType">API 的返回类型</typeparam>
[AttributeUsage(AttributeTargets.Method)]
internal sealed class ApiInformationAttribute : Attribute
{

View File

@@ -0,0 +1,25 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Web.Hutao.GachaLog;
/// <summary>
/// 祈愿活动统计
/// </summary>
internal sealed class GachaEventStatistics
{
/// <summary>
/// 角色活动1
/// </summary>
public List<ItemCount> AvatarEvent { get; set; } = default!;
/// <summary>
/// 角色活动2
/// </summary>
public List<ItemCount> AvatarEvent2 { get; set; } = default!;
/// <summary>
/// 武器活动
/// </summary>
public List<ItemCount> WeaponEvent { get; set; } = default!;
}

View File

@@ -36,4 +36,4 @@ internal sealed class GachaItem
/// Id
/// </summary>
public long Id { get; set; }
}
}

View File

@@ -0,0 +1,20 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Web.Hutao.GachaLog;
/// <summary>
/// 物品与个数
/// </summary>
internal sealed class ItemCount
{
/// <summary>
/// 物品 Id
/// </summary>
public uint Item { get; set; }
/// <summary>
/// 个数
/// </summary>
public uint Count { get; set; }
}

View File

@@ -35,7 +35,19 @@ internal sealed class HomaGachaLogClient
httpClient.DefaultRequestHeaders.Authorization = new("Bearer", hutaoUserOptions.Token);
}
/// <summary>
/// 异步获取祈愿统计信息
/// </summary>
/// <param name="token">取消令牌</param>
/// <returns>祈愿统计信息</returns>
public async Task<Response<GachaEventStatistics>> GetGachaEventStatisticsAsync(CancellationToken token = default)
{
Response<GachaEventStatistics>? resp = await httpClient
.TryCatchGetFromJsonAsync<Response<GachaEventStatistics>>(HutaoEndpoints.GachaLogUids, options, logger, token)
.ConfigureAwait(false);
return Response.Response.DefaultIfNull(resp);
}
/// <summary>
/// 异步获取 Uid 列表

View File

@@ -52,6 +52,11 @@ internal static class HutaoEndpoints
{
return $"{HomaSnapGenshinApi}/GachaLog/Delete?Uid={uid}";
}
/// <summary>
/// 获取祈愿统计信息
/// </summary>
public const string GachaLogStatisticsCurrentEvents = $"{HomaSnapGenshinApi}/GachaLog/Statistics/CurrentEventStatistics";
#endregion
#region Passport