Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 29 additions & 2 deletions Authentication/MicrosoftAuthentication.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
var resultDict = new RetrieveDeviceCode
{
ClientId = ClientId,
UserCode = responseDict.UserCode,

Check warning on line 58 in Authentication/MicrosoftAuthentication.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.
DeviceCode = responseDict.DeviceCode,
VerificationUri = responseDict.VerificationUri,
Message = responseDict.Message
Expand Down Expand Up @@ -95,7 +95,7 @@
if (tokenRes.IsSuccessStatusCode)
{
var tokenData = tokenJson.ToJsonEntry<GetTokenResponse>();
if (!string.IsNullOrEmpty(tokenData.AccessToken))

Check warning on line 98 in Authentication/MicrosoftAuthentication.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.
return new GetTokenResponse
{
ExpiresIn = tokenData.ExpiresIn,
Expand All @@ -104,6 +104,33 @@
ClientId = deviceCodeInfo.ClientId
};
}
else
{
// 先判断是否正在等待中,直接使用 Contains,避免额外解析开销
if (!tokenJson.Contains("authorization_pending"))
{
try
{
var errorData = tokenJson.ToJsonEntry<GetTokenErrorResponse>();
switch (errorData.Error)

Check warning on line 115 in Authentication/MicrosoftAuthentication.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.
{
case "authorization_declined":
throw new Exception("用户拒绝了授权");
case "bad_verification_code":
throw new Exception("提交的 device_code 无效");
case "expired_token":
throw new Exception("登录已超时,请重试"); // 避免轮询时正好过期导致抓不到异常
default:
throw new Exception(errorData.Error);
// 实际上还有其他的错误类型,但按理说不会出现,比如 slow_down
}
}
catch (Exception e)
{
throw new Exception("轮询获取 Token 错误:" + e.Message);
}
}
}

await Task.Delay(pollingInterval);
}
Expand All @@ -124,7 +151,7 @@
string? refreshToken = null)
{
if (refreshToken == null) return await GetMicrosoftAuthInfo(tokenInfo, action);

// 刷新令牌
action("正在刷新令牌");

Expand All @@ -143,7 +170,7 @@

var refreshResponseData = refreshResponse.ToJsonEntry<TokenResponse>();

tokenInfo.AccessToken = refreshResponseData.AccessToken;

Check warning on line 173 in Authentication/MicrosoftAuthentication.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.
tokenInfo.RefreshToken = refreshResponseData.RefreshToken;
tokenInfo.ExpiresIn = refreshResponseData.ExpiresIn;

Expand Down Expand Up @@ -270,7 +297,7 @@

var minecraftProfile = profileContent.ToJsonEntry<MinecraftProfile>();
if (minecraftProfile == null) throw new Exception("验证失败");

var uuid = minecraftProfile.Uuid;
var name = minecraftProfile.Name;
var skinUrl = minecraftProfile.Skins[0].Url;
Expand Down
16 changes: 16 additions & 0 deletions Models/Authentication/GetTokenErrorResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Text.Json.Serialization;

namespace StarLight_Core.Models.Authentication;

/// <summary>
/// 令牌错误信息
/// </summary>
/// <a href="https://wiki.conlux.studio/Authentication/Microsoft.html#详细-gettokenresponse-定义">查看文档</a>
public class GetTokenErrorResponse
{
/// <summary>
/// 错误
/// </summary>
[JsonPropertyName("error")]
public string Error { get; set; }
}
12 changes: 12 additions & 0 deletions Skin/Fetchers/MicrosoftSkinFetcher.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Text;
using StarLight_Core.Models.Authentication;
using StarLight_Core.Models.Skin;
using StarLight_Core.Utilities;

Expand All @@ -9,6 +10,16 @@ namespace StarLight_Core.Skin.Fetchers;
/// </summary>
public class MicrosoftSkinFetcher
{
/// <summary>
/// 获取微软皮肤
/// </summary>
/// <param name="account">皮肤图片字节信息</param>
/// <returns>皮肤图片字节信息</returns>
public static async Task<byte[]> GetMicrosoftSkinAsync(MicrosoftAccount account)
{
return await GetMicrosoftSkinAsync(account.Uuid);
}

/// <summary>
/// 获取微软皮肤
/// </summary>
Expand All @@ -17,6 +28,7 @@ public class MicrosoftSkinFetcher
public static async Task<byte[]> GetMicrosoftSkinAsync(string uuid)
{
const string baseUrl = "https://sessionserver.mojang.com/session/minecraft/profile/";
uuid = uuid.Replace("-", "");
var skinJson = await HttpUtil.GetStringAsync(baseUrl + uuid);
var skinUrl =
Encoding.UTF8.GetString(
Expand Down
45 changes: 45 additions & 0 deletions Skin/Fetchers/YggdrasilSkinFetcher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using StarLight_Core.Models.Authentication;
using StarLight_Core.Models.Skin;
using StarLight_Core.Utilities;
using System.Security.Cryptography.X509Certificates;
using System.Security.Principal;
using System.Text;

namespace StarLight_Core.Skin.Fetchers;

/// <summary>
/// 外置皮肤获取器
/// </summary>
public class YggdrasilSkinFetcher
{
/// <summary>
/// 获取外置皮肤
/// </summary>
/// <param name="account">外置账户</param>
/// <returns>皮肤图片字节信息</returns>
public static async Task<byte[]> GetYggdrasilSkinAsync(YggdrasilAccount account)
{
return await GetYggdrasilSkinAsync(account.ServerUrl, account.Uuid);
}

/// <summary>
/// 获取外置皮肤
/// </summary>
/// <param name="serverUrl">服务器 Url</param>
/// <param name="uuid">外置账户 Uuid</param>
/// <returns>皮肤图片字节信息</returns>
public static async Task<byte[]> GetYggdrasilSkinAsync(string serverUrl, string uuid)
{
var baseUrl = serverUrl.TrimEnd("/");

Check failure on line 33 in Skin/Fetchers/YggdrasilSkinFetcher.cs

View workflow job for this annotation

GitHub Actions / build

Argument 1: cannot convert from 'string' to 'char'

Check failure on line 33 in Skin/Fetchers/YggdrasilSkinFetcher.cs

View workflow job for this annotation

GitHub Actions / build

Argument 1: cannot convert from 'string' to 'char'

Check failure on line 33 in Skin/Fetchers/YggdrasilSkinFetcher.cs

View workflow job for this annotation

GitHub Actions / build

Argument 1: cannot convert from 'string' to 'char'

Check failure on line 33 in Skin/Fetchers/YggdrasilSkinFetcher.cs

View workflow job for this annotation

GitHub Actions / build

Argument 1: cannot convert from 'string' to 'char'

Check failure on line 33 in Skin/Fetchers/YggdrasilSkinFetcher.cs

View workflow job for this annotation

GitHub Actions / build

Argument 1: cannot convert from 'string' to 'char'

Check failure on line 33 in Skin/Fetchers/YggdrasilSkinFetcher.cs

View workflow job for this annotation

GitHub Actions / build

Argument 1: cannot convert from 'string' to 'char'
uuid = uuid.Replace("-", "");
var skinJson = await HttpUtil.GetStringAsync($"{baseUrl}/sessionserver/session/minecraft/profile/{uuid}");
var skinUrl =
Encoding.UTF8.GetString(
Convert.FromBase64String(
skinJson.ToJsonEntry<ProfileJsonEntity>().Properties.First().Value))
.ToJsonEntry<SkinJsonEntity>()
.Textures.Skin.Url;
using var httpClient = new HttpClient();
return await httpClient.GetByteArrayAsync(skinUrl);
}
}
Loading