mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
Hutao GachaEvent Statistics 1
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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()
|
||||
@@ -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'
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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!;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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!;
|
||||
}
|
||||
@@ -36,4 +36,4 @@ internal sealed class GachaItem
|
||||
/// Id
|
||||
/// </summary>
|
||||
public long Id { get; set; }
|
||||
}
|
||||
}
|
||||
20
src/Snap.Hutao/Snap.Hutao/Web/Hutao/GachaLog/ItemCount.cs
Normal file
20
src/Snap.Hutao/Snap.Hutao/Web/Hutao/GachaLog/ItemCount.cs
Normal 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; }
|
||||
}
|
||||
@@ -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 列表
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user