Обнновлено до .net10
This commit is contained in:
300
YandexMusic.API/API/YUserAPI.cs
Normal file
300
YandexMusic.API/API/YUserAPI.cs
Normal 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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user