mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
support getWidgetData for #207
This commit is contained in:
@@ -46,6 +46,6 @@ internal static class IocConfiguration
|
||||
}
|
||||
}
|
||||
|
||||
return services.AddDbContextPool<AppDbContext>(builder => builder.UseSqlite(sqlConnectionString));
|
||||
return services.AddDbContext<AppDbContext>(builder => builder.UseSqlite(sqlConnectionString));
|
||||
}
|
||||
}
|
||||
@@ -54,11 +54,12 @@ public static class Must
|
||||
/// <summary>
|
||||
/// Unconditionally throws an <see cref="NotSupportedException"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">上下文</param>
|
||||
/// <returns>Nothing. This method always throws.</returns>
|
||||
[DoesNotReturn]
|
||||
public static System.Exception NeverHappen()
|
||||
public static System.Exception NeverHappen(string? context = null)
|
||||
{
|
||||
throw new NotSupportedException("该行为不应发生,请联系开发者进一步确认");
|
||||
throw new NotSupportedException(context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -182,7 +182,7 @@ internal sealed class ExtendedWindow<TWindow> : IRecipient<BackdropTypeChangedMe
|
||||
|
||||
// workaround for https://github.com/microsoft/WindowsAppSDK/issues/2976
|
||||
SizeInt32 size = appWindow.ClientSize;
|
||||
size.Height -= 38;
|
||||
size.Height -= (int)(31 * scale);
|
||||
appWindow.ResizeClient(size);
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ using Snap.Hutao.Model.Binding.Hutao;
|
||||
using Snap.Hutao.Model.Intrinsic;
|
||||
using Snap.Hutao.Model.Metadata.Abstraction;
|
||||
using Snap.Hutao.Model.Metadata.Converter;
|
||||
using Snap.Hutao.Model.Primitive;
|
||||
|
||||
namespace Snap.Hutao.Model.Metadata.Avatar;
|
||||
|
||||
@@ -18,7 +19,7 @@ public class Avatar : IStatisticsItemSource, ISummaryItemSource, INameQuality
|
||||
/// <summary>
|
||||
/// Id
|
||||
/// </summary>
|
||||
public int Id { get; set; }
|
||||
public AvatarId Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序号
|
||||
@@ -88,6 +89,7 @@ public class Avatar : IStatisticsItemSource, ISummaryItemSource, INameQuality
|
||||
/// <summary>
|
||||
/// [非元数据] 搭配数据
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public ComplexAvatarCollocation? Collocation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@@ -118,6 +120,7 @@ public class Avatar : IStatisticsItemSource, ISummaryItemSource, INameQuality
|
||||
Icon = AvatarIconConverter.IconNameToUri(Icon),
|
||||
Badge = ElementNameIconConverter.ElementNameToIconUri(FetterInfo.VisionBefore),
|
||||
Quality = Quality,
|
||||
|
||||
Count = count,
|
||||
};
|
||||
}
|
||||
@@ -137,6 +140,7 @@ public class Avatar : IStatisticsItemSource, ISummaryItemSource, INameQuality
|
||||
Icon = AvatarIconConverter.IconNameToUri(Icon),
|
||||
Badge = ElementNameIconConverter.ElementNameToIconUri(FetterInfo.VisionBefore),
|
||||
Quality = Quality,
|
||||
|
||||
Time = time,
|
||||
LastPull = lastPull,
|
||||
IsUp = isUp,
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace Snap.Hutao.Model.Metadata.Converter;
|
||||
internal class ElementNameIconConverter : ValueConverterBase<string, Uri>
|
||||
{
|
||||
private const string BaseUrl = "https://static.snapgenshin.com/IconElement/UI_Icon_Element_{0}.png";
|
||||
private static readonly Uri UIIconNone = new("https://static.snapgenshin.com/Bg/UI_Icon_None.png");
|
||||
|
||||
/// <summary>
|
||||
/// 将中文元素名称转换为图标链接
|
||||
@@ -28,10 +29,12 @@ internal class ElementNameIconConverter : ValueConverterBase<string, Uri>
|
||||
"岩" => "Rock",
|
||||
"水" => "Water",
|
||||
"风" => "Wind",
|
||||
_ => throw Must.NeverHappen(),
|
||||
_ => string.Empty,
|
||||
};
|
||||
|
||||
return new Uri(string.Format(BaseUrl, element));
|
||||
return string.IsNullOrEmpty(element)
|
||||
? UIIconNone
|
||||
: new Uri(string.Format(BaseUrl, element));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Model.Primitive.Converter;
|
||||
using Windows.ApplicationModel.Chat;
|
||||
|
||||
namespace Snap.Hutao.Model.Primitive;
|
||||
|
||||
@@ -62,4 +63,4 @@ public readonly struct AvatarId : IEquatable<AvatarId>
|
||||
{
|
||||
return Value.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Snap.Hutao.Web.Hoyolab.Annotation;
|
||||
|
||||
/// <summary>
|
||||
/// API 信息
|
||||
/// </summary>
|
||||
/// <typeparam name="TReturnType">API 的返回类型</typeparam>
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
internal class ApiInformationAttribute<TReturnType> : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Cookie类型
|
||||
/// </summary>
|
||||
public CookieType Cookie { get; set; }
|
||||
}
|
||||
@@ -145,13 +145,25 @@ internal static class ApiEndpoints
|
||||
// https://sdk-static.mihoyo.com/hk4e_cn/mdk/launcher/api/content?key=eYd89JmJ&language=zh-cn&launcher_id=18
|
||||
#endregion
|
||||
|
||||
#region App
|
||||
|
||||
/// <summary>
|
||||
/// 小组件数据
|
||||
/// </summary>
|
||||
public const string AppWidgetData = $"{AppCardApi}/getWidgetData?game_id=2";
|
||||
#endregion
|
||||
|
||||
// consts
|
||||
private const string ApiTakumi = "https://api-takumi.mihoyo.com";
|
||||
private const string ApiTakumiAuthApi = $"{ApiTakumi}/auth/api";
|
||||
private const string ApiTaKumiBindingApi = $"{ApiTakumi}/binding/api";
|
||||
|
||||
private const string ApiTakumiRecord = "https://api-takumi-record.mihoyo.com";
|
||||
private const string ApiTakumiRecordApi = $"{ApiTakumiRecord}/game_record/app/genshin/api";
|
||||
|
||||
private const string App = "https://app.mihoyo.com";
|
||||
private const string AppCardApi = $"{App}/game_record/app/card/api";
|
||||
|
||||
private const string BbsApi = "https://bbs-api.mihoyo.com";
|
||||
private const string BbsApiUserApi = $"{BbsApi}/user/wapi";
|
||||
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
|
||||
using Snap.Hutao.Model.Entity;
|
||||
using Snap.Hutao.Web.Hoyolab.Annotation;
|
||||
using Snap.Hutao.Web.Response;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace Snap.Hutao.Web.Hoyolab.App.GameRecord;
|
||||
|
||||
/// <summary>
|
||||
/// 桌面卡片客户端
|
||||
/// </summary>
|
||||
[HttpClient(HttpClientConfigration.XRpc)]
|
||||
internal class CardClient
|
||||
{
|
||||
private readonly HttpClient httpClient;
|
||||
private readonly JsonSerializerOptions options;
|
||||
private readonly ILogger<CardClient> logger;
|
||||
|
||||
/// <summary>
|
||||
/// 构造一个新的桌面卡片客户端
|
||||
/// </summary>
|
||||
/// <param name="httpClient">http客户端</param>
|
||||
/// <param name="options">选项</param>
|
||||
/// <param name="logger">日志器</param>
|
||||
public CardClient(HttpClient httpClient, JsonSerializerOptions options, ILogger<CardClient> logger)
|
||||
{
|
||||
this.httpClient = httpClient;
|
||||
this.options = options;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步获取桌面小组件数据
|
||||
/// </summary>
|
||||
/// <param name="user">用户</param>
|
||||
/// <param name="token">取消令牌</param>
|
||||
/// <returns>桌面小组件数据</returns>
|
||||
[ApiInformation<WidgetData>(Cookie = CookieType.Stoken)]
|
||||
public async Task<WidgetData?> GetWidgetDataAsync(User user, CancellationToken token)
|
||||
{
|
||||
Response<DataWrapper<WidgetData>>? resp = await httpClient
|
||||
.SetUser(user, CookieType.Stoken)
|
||||
.TryCatchGetFromJsonAsync<Response<DataWrapper<WidgetData>>>(ApiEndpoints.UserFullInfo, options, logger, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return resp?.Data?.Data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
|
||||
|
||||
namespace Snap.Hutao.Web.Hoyolab.App.GameRecord;
|
||||
|
||||
/// <summary>
|
||||
/// 小组件数据
|
||||
/// </summary>
|
||||
public class WidgetData
|
||||
{
|
||||
/// <summary>
|
||||
/// 游戏Id 2
|
||||
/// </summary>
|
||||
[JsonPropertyName("game_id")]
|
||||
public int GameId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 游戏内Uid
|
||||
/// </summary>
|
||||
[JsonPropertyName("game_role_id")]
|
||||
public string GameRoleId { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 昵称
|
||||
/// </summary>
|
||||
[JsonPropertyName("nickname")]
|
||||
public string Nickname { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 区服
|
||||
/// </summary>
|
||||
[JsonPropertyName("region")]
|
||||
public string Region { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 冒险等阶
|
||||
/// </summary>
|
||||
[JsonPropertyName("level")]
|
||||
public int Level { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 背景图片
|
||||
/// </summary>
|
||||
[JsonPropertyName("background_image")]
|
||||
public string BackgroundImage { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 数据
|
||||
/// </summary>
|
||||
[JsonPropertyName("data")]
|
||||
public List<WidgetDataItem> Data { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 区服名称
|
||||
/// </summary>
|
||||
[JsonPropertyName("region_name")]
|
||||
public string RegionName { get; set; } = default!;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using Snap.Hutao.Core.DependencyInjection.Annotation.HttpClient;
|
||||
|
||||
namespace Snap.Hutao.Web.Hoyolab.App.GameRecord;
|
||||
|
||||
/// <summary>
|
||||
/// 小组件数据项
|
||||
/// </summary>
|
||||
public class WidgetDataItem
|
||||
{
|
||||
/// <summary>
|
||||
/// 项目名称
|
||||
/// </summary>
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 类型 均为 "String"
|
||||
/// </summary>
|
||||
[JsonPropertyName("type")]
|
||||
public string Type { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// 显示值
|
||||
/// </summary>
|
||||
[JsonPropertyName("value")]
|
||||
public string Value { get; set; } = default!;
|
||||
}
|
||||
@@ -39,10 +39,10 @@ internal class UserClient
|
||||
public async Task<UserInfo?> GetUserFullInfoAsync(Model.Binding.User.User user, CancellationToken token = default)
|
||||
{
|
||||
Response<UserFullInfoWrapper>? resp = await httpClient
|
||||
.SetUser(user)
|
||||
.SetReferer(ApiEndpoints.BbsReferer)
|
||||
.TryCatchGetFromJsonAsync<Response<UserFullInfoWrapper>>(ApiEndpoints.UserFullInfo, options, logger, token)
|
||||
.ConfigureAwait(false);
|
||||
.SetUser(user)
|
||||
.SetReferer(ApiEndpoints.BbsReferer)
|
||||
.TryCatchGetFromJsonAsync<Response<UserFullInfoWrapper>>(ApiEndpoints.UserFullInfo, options, logger, token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return resp?.Data?.UserInfo;
|
||||
}
|
||||
|
||||
@@ -21,4 +21,6 @@ public partial class Cookie
|
||||
|
||||
public const string STOKEN = "stoken";
|
||||
public const string STUID = "stuid";
|
||||
|
||||
public const string MID = "mid";
|
||||
}
|
||||
|
||||
@@ -192,12 +192,32 @@ public partial class Cookie
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据类型输出对应的Cookie
|
||||
/// </summary>
|
||||
/// <param name="type">类型</param>
|
||||
/// <returns>Cookie对应的字符串表示</returns>
|
||||
public string ToString(CookieType type)
|
||||
{
|
||||
IEnumerable<KeyValuePair<string, string>> results;
|
||||
|
||||
results = type switch
|
||||
{
|
||||
CookieType.None => Enumerable.Empty<KeyValuePair<string, string>>(),
|
||||
CookieType.Stoken => inner.Where(kvp => kvp.Key is STUID or STOKEN or MID),
|
||||
CookieType.All => inner,
|
||||
_ => throw Must.NeverHappen(type.ToString()),
|
||||
};
|
||||
|
||||
return string.Join(';', results.Select(kvp => $"{kvp.Key}={kvp.Value}"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换为Cookie的字符串表示
|
||||
/// </summary>
|
||||
/// <returns>Cookie的字符串表示</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Join(';', inner.Select(kvp => $"{kvp.Key}={kvp.Value}"));
|
||||
return ToString(CookieType.All);
|
||||
}
|
||||
}
|
||||
25
src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/CookieType.cs
Normal file
25
src/Snap.Hutao/Snap.Hutao/Web/Hoyolab/CookieType.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Web.Hoyolab;
|
||||
|
||||
/// <summary>
|
||||
/// Cookie 类型
|
||||
/// </summary>
|
||||
public enum CookieType
|
||||
{
|
||||
/// <summary>
|
||||
/// 不需要 Cookie
|
||||
/// </summary>
|
||||
None,
|
||||
|
||||
/// <summary>
|
||||
/// 需要 Stoken
|
||||
/// </summary>
|
||||
Stoken,
|
||||
|
||||
/// <summary>
|
||||
/// 全部
|
||||
/// </summary>
|
||||
All,
|
||||
}
|
||||
@@ -66,6 +66,7 @@ internal static class HttpClientExtensions
|
||||
/// <param name="httpClient">http客户端</param>
|
||||
/// <param name="user">绑定用户</param>
|
||||
/// <returns>客户端</returns>
|
||||
[Obsolete("请使用带有 type 的重载")]
|
||||
internal static HttpClient SetUser(this HttpClient httpClient, User user)
|
||||
{
|
||||
httpClient.DefaultRequestHeaders.Set("Cookie", user.Cookie!.ToString());
|
||||
@@ -77,10 +78,11 @@ internal static class HttpClientExtensions
|
||||
/// </summary>
|
||||
/// <param name="httpClient">http客户端</param>
|
||||
/// <param name="user">实体用户</param>
|
||||
/// <param name="type">Cookie类型</param>
|
||||
/// <returns>客户端</returns>
|
||||
internal static HttpClient SetUser(this HttpClient httpClient, Model.Entity.User user)
|
||||
internal static HttpClient SetUser(this HttpClient httpClient, Model.Entity.User user, CookieType type = CookieType.All)
|
||||
{
|
||||
httpClient.DefaultRequestHeaders.Set("Cookie", user.Cookie!.ToString());
|
||||
httpClient.DefaultRequestHeaders.Set("Cookie", user.Cookie!.ToString(type));
|
||||
return httpClient;
|
||||
}
|
||||
|
||||
|
||||
17
src/Snap.Hutao/Snap.Hutao/Web/Response/DataWrapper.cs
Normal file
17
src/Snap.Hutao/Snap.Hutao/Web/Response/DataWrapper.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright (c) DGP Studio. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
namespace Snap.Hutao.Web.Response;
|
||||
|
||||
/// <summary>
|
||||
/// 数据对象包装器
|
||||
/// </summary>
|
||||
/// <typeparam name="T">数据类型</typeparam>
|
||||
public class DataWrapper<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// 数据
|
||||
/// </summary>
|
||||
[JsonPropertyName("data")]
|
||||
public T Data { get; set; } = default!;
|
||||
}
|
||||
@@ -23,6 +23,11 @@ public enum KnownReturnCode : int
|
||||
/// </summary>
|
||||
RET_NEED_RISK_VERIFY = -3235,
|
||||
|
||||
/// <summary>
|
||||
/// 验证码已失效,请重新获取
|
||||
/// </summary>
|
||||
VerifyCodeOutdated = -3209,
|
||||
|
||||
/// <summary>
|
||||
/// 禁止
|
||||
/// </summary>
|
||||
|
||||
@@ -14,4 +14,4 @@ public class ListWrapper<T>
|
||||
/// </summary>
|
||||
[JsonPropertyName("list")]
|
||||
public List<T> List { get; set; } = default!;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user