Обнновлено до .net10

This commit is contained in:
FrigaT
2026-04-10 15:05:32 +03:00
parent 11d0b0d72f
commit 8444fc5f8e
386 changed files with 6361 additions and 7164 deletions

View File

@@ -0,0 +1,300 @@
using System.Security.Authentication;
using System.Text.RegularExpressions;
using YandexMusic.API.Common;
using YandexMusic.API.Models.Account;
using YandexMusic.API.Models.Common;
using YandexMusic.API.Requests.Account;
namespace YandexMusic.API;
/// <summary>
/// API для пользователя
/// </summary>
public partial class YUserAPI : YCommonAPI
{
#region Вспомогательные функции
private async Task<bool> GetCsrfTokenAsync(AuthStorage storage)
{
using HttpResponseMessage authMethodsResponse = await new YGetAuthMethodsBuilder(api, storage)
.Build(null)
.GetResponseAsync();
if (!authMethodsResponse.IsSuccessStatusCode)
throw new HttpRequestException("Невозможно получить CFRF-токен.");
string responseString = await authMethodsResponse.Content
.ReadAsStringAsync();
Match match = Regex.Match(responseString, "\"csrf_token\" value=\"([^\"]+)\"");
if (!match.Success || match.Groups.Count < 2)
return false;
storage.AuthToken = new YAuthToken
{
CsfrToken = match.Groups[1].Value
};
return true;
}
private async Task<bool> LoginByCookiesAsync(AuthStorage storage)
{
if (storage.AuthToken == null)
throw new AuthenticationException("Невозможно инициализировать сессию входа.");
YAccessToken accessToken = await new YGetAuthCookiesBuilder(api, storage)
.Build(null)
.GetResponseAsync();
storage.IsAuthorized = !string.IsNullOrEmpty(accessToken.AccessToken);
storage.AccessToken = accessToken;
storage.Token = accessToken.AccessToken;
YShortAccountInfo validateTokenResponse = await new YGetShortAccountInifoBuilder(api, storage)
.Build(null)
.GetResponseAsync();
if (validateTokenResponse.Status != YAuthStatus.Ok)
throw new Exception("Вход в аккаунт не выполнен.");
storage.IsAuthorized = !string.IsNullOrWhiteSpace(validateTokenResponse.Uid);
return storage.IsAuthorized;
}
#endregion Вспомогательные функции
public YUserAPI(YandexMusicApi yandex) : base(yandex)
{
}
/// <summary>
/// Авторизация
/// </summary>
/// <param name="storage">Хранилище</param>
/// <param name="token">Токен авторизации</param>
/// <returns></returns>
public async Task AuthorizeAsync(AuthStorage storage, string token)
{
if (string.IsNullOrEmpty(token))
throw new Exception("Задан пустой токен авторизации.");
storage.Token = token;
// Пытаемся получить информацию о пользователе
YResponse<YAccountResult> authInfo = await GetUserAuthAsync(storage);
// Если не авторизован, то авторизуем
if (string.IsNullOrEmpty(authInfo.Result.Account.Uid))
throw new Exception("Пользователь незалогинен.");
// Флаг авторизации
storage.IsAuthorized = true;
storage.User = authInfo.Result.Account;
}
/// <summary>
/// Получение информации об авторизации
/// </summary>
/// <param name="storage">Хранилище</param>
/// <returns></returns>
public Task<YResponse<YAccountResult>> GetUserAuthAsync(AuthStorage storage)
{
return new YGetAuthInfoBuilder(api, storage)
.Build(null)
.GetResponseAsync();
}
/// <summary>
/// Создание сеанса и получение доступных методов авторизации
/// </summary>
/// <param name="storage">Хранилище</param>
/// <param name="userName">Имя пользователя</param>
/// <returns></returns>
public async Task<YAuthTypes> CreateAuthSessionAsync(AuthStorage storage, string userName)
{
if (!await GetCsrfTokenAsync(storage))
throw new Exception("Невозможно инициализировать сессию входа.");
YAuthTypes types = await new YGetAuthLoginUserBuilder(api, storage)
.Build((storage.AuthToken.CsfrToken, userName))
.GetResponseAsync();
storage.AuthToken.TrackId = types.TrackId;
return types;
}
/// <summary>
/// Получение ссылки на QR-код
/// </summary>
/// <param name="storage">Хранилище</param>
/// <returns></returns>
public async Task<string> GetAuthQRLinkAsync(AuthStorage storage)
{
if (!await GetCsrfTokenAsync(storage))
throw new Exception("Невозможно инициализировать сессию входа.");
YAuthQR result = await new YGetAuthQRBuilder(api, storage)
.Build(null)
.GetResponseAsync();
if (result.Status != YAuthStatus.Ok)
return string.Empty;
storage.AuthToken = new YAuthToken
{
TrackId = result.TrackId,
CsfrToken = result.CsrfToken
};
return $"https://passport.yandex.ru/auth/magic/code/?track_id={result.TrackId}";
}
/// <summary>
/// Авторизация по QR-коду
/// </summary>
/// <param name="storage">Хранилище</param>
/// <returns></returns>
public async Task<YAuthQRStatus> AuthorizeByQRAsync(AuthStorage storage)
{
if (storage.AuthToken == null)
throw new Exception("Не выполнен запрос на авторизацию по QR.");
try
{
YAuthQRStatus qrStatus = await new YGetAuthLoginQRBuilder(api, storage)
.Build(null)
.GetResponseAsync();
if (qrStatus.Status != YAuthStatus.Ok)
return qrStatus;
bool ok = await LoginByCookiesAsync(storage);
if (!ok)
throw new AuthenticationException("Ошибка авторизации по QR.");
return qrStatus;
}
catch (Exception ex)
{
throw new AuthenticationException("Ошибка авторизации по QR.", ex);
}
}
/// <summary>
/// Получение <see cref="YAuthCaptcha"/>
/// </summary>
/// <param name="storage">Хранилище</param>
/// <returns></returns>
public Task<YAuthCaptcha> GetCaptchaAsync(AuthStorage storage)
{
if (storage.AuthToken == null || string.IsNullOrWhiteSpace(storage.AuthToken.CsfrToken))
throw new AuthenticationException($"Не найдена сессия входа. Выполните {nameof(CreateAuthSessionAsync)} перед использованием.");
return new YGetAuthCaptchaBuilder(api, storage)
.Build(null)
.GetResponseAsync();
}
/// <summary>
/// Авторизация по captcha
/// </summary>
/// <param name="storage">Хранилище</param>
/// <param name="captchaValue">Значение captcha</param>
/// <returns></returns>
public Task<YAuthBase> AuthorizeByCaptchaAsync(AuthStorage storage, string captchaValue)
{
if (storage.AuthToken == null || string.IsNullOrWhiteSpace(storage.AuthToken.CsfrToken))
throw new AuthenticationException($"Не найдена сессия входа. Выполните {nameof(CreateAuthSessionAsync)} перед использованием.");
return new YGetAuthLoginCaptchaBuilder(api, storage)
.Build(captchaValue)
.GetResponseAsync();
}
/// <summary>
/// Получение письма авторизации на почту пользователя
/// </summary>
/// <param name="storage">Хранилище</param>
/// <returns></returns>
public Task<YAuthLetter> GetAuthLetterAsync(AuthStorage storage)
{
return new YGetAuthLetterBuilder(api, storage)
.Build(null)
.GetResponseAsync();
}
/// <summary>
/// Авторизация после подтверждения входа через письмо
/// </summary>
/// <param name="storage">Хранилище</param>
/// <returns></returns>
public async Task<bool> AuthorizeByLetterAsync(AuthStorage storage)
{
YAuthLetterStatus status = await new YGetAuthLoginLetterBuilder(api, storage)
.Build(null)
.GetResponseAsync();
if (status.Status == YAuthStatus.Ok && !status.MagicLinkConfirmed)
throw new Exception("Не подтвержден вход посредством e-mail.");
return await LoginByCookiesAsync(storage);
}
/// <summary>
/// Авторизация с помощью пароля из приложения Яндекс
/// </summary>
/// <param name="storage">Хранилище</param>
/// <param name="password">Пароль</param>
/// <returns></returns>
public async Task<YAuthBase> AuthorizeByAppPasswordAsync(AuthStorage storage, string password)
{
if (storage.AuthToken == null || string.IsNullOrWhiteSpace(storage.AuthToken.CsfrToken))
throw new AuthenticationException($"Не найдена сессия входа. Выполните {nameof(CreateAuthSessionAsync)} перед использованием.");
YAuthBase response = await new YGetAuthAppPasswordBuilder(api, storage)
.Build(password)
.GetResponseAsync();
if (response.Status == YAuthStatus.Ok)
{
bool ok = await LoginByCookiesAsync(storage);
if (!ok)
throw new AuthenticationException("Ошибка авторизации.");
}
return response;
}
/// <summary>
/// Получение <see cref="YAccessToken"/> после авторизации с помощью QR, e-mail, пароля из приложения
/// </summary>
public async Task<YAccessToken> GetAccessTokenAsync(AuthStorage storage)
{
if (storage.AuthToken == null)
throw new Exception("Не найдена сессия входа.");
YAccessToken accessToken = await new YGetMusicTokenBuilder(api, storage)
.Build(null)
.GetResponseAsync();
storage.Token = accessToken.AccessToken;
return accessToken;
}
/// <summary>
/// Получение информации о пользователе через логин Яндекса
/// </summary>
public Task<YLoginInfo> GetLoginInfoAsync(AuthStorage storage)
{
return new YGetLoginInfoBuilder(api, storage)
.Build(null)
.GetResponseAsync();
}
}