using Microsoft.AspNetCore.DataProtection;
using PlaylistShared.Api.Entities;
using System.Net;
using YandexMusic;
namespace PlaylistShared.Api.Services;
///
/// Сервис для работы с API Яндекс Музыки в ASP.NET Core.
///
public class YandexApiService : IDisposable
{
private readonly IDataProtector _dataProtector;
private readonly YandexMusicClient _client;
private readonly CookieContainer _cookieContainer;
///
/// Экземпляр клиента Яндекс Музыки.
///
public YandexMusicClient Client => _client;
///
/// Контейнер кук, используемый клиентом.
///
public CookieContainer CookieContainer => _cookieContainer;
///
/// Создаёт сервис с автоматическим созданием HttpClient (рекомендуется).
///
public YandexApiService(IDataProtectionProvider provider, IWebProxy? proxy = null, TimeSpan? timeout = null)
{
_dataProtector = provider.CreateProtector("YandexTokens");
_cookieContainer = new();
_client = new YandexMusicClient(_cookieContainer, proxy, timeout);
}
public async Task AuthAsync(ApplicationUser user)
{
if (string.IsNullOrEmpty(user.YandexAccessToken))
return null;
var decryptedToken = DecryptToken(user.YandexAccessToken);
if (decryptedToken == null)
return null;
return await AuthorizeAsync(decryptedToken);
}
///
/// Авторизуется с помощью OAuth-токена.
///
public async Task AuthAsync(string token)
{
return await AuthorizeAsync(token);
}
private async Task AuthorizeAsync(string token)
{
try
{
await _client.Api.Auth.AuthorizeAsync(token);
return true;
}
catch
{
return false;
}
}
///
/// Засшифровывает и возвращает токен для хранения в базе данных.
///
///
///
public string EncryptToken(string token) => _dataProtector.Protect(token);
///
/// Расшифровывает ключ из базы данных. Если токен повреждён или недействителен, возвращает null.
///
///
///
public string DecryptToken(string encryptedToken)
{
try
{
return _dataProtector.Unprotect(encryptedToken);
}
catch
{
return null;
}
}
///
/// Устанавливает куки из строки для указанного домена.
///
public void SetCookies(string cookieString, string domain)
{
var uri = new Uri(domain.StartsWith("http") ? domain : $"https://{domain}");
_cookieContainer.SetCookies(uri, cookieString);
}
///
/// Получает все куки для указанного домена в виде строки.
///
public string GetCookies(string domain)
{
var uri = new Uri(domain.StartsWith("http") ? domain : $"https://{domain}");
var cookies = _cookieContainer.GetCookies(uri);
return string.Join("; ", cookies.Cast().Select(c => $"{c.Name}={c.Value}"));
}
///
/// Получает значение конкретной куки.
///
public string? GetCookie(string domain, string cookieName)
{
var uri = new Uri(domain.StartsWith("http") ? domain : $"https://{domain}");
var cookie = _cookieContainer.GetCookies(uri)[cookieName];
return cookie?.Value;
}
public void Dispose()
{
_client.Dispose();
}
}