using PlaylistShared.Api.Data; using PlaylistShared.Api.Entities; using PlaylistShared.Shared.Yandex; using System.Net; using System.Text.Json; using YandexMusic.API.Models.Account; namespace PlaylistShared.Api.Services; public class YandexAuthService { private readonly YandexApiService _apiService; private readonly ApplicationDbContext _dbContext; public YandexApiService Service => _apiService; public YandexAuthService(YandexApiService apiService, ApplicationDbContext dbContext) { _apiService = apiService; _dbContext = dbContext; } internal async Task GenerateQrAsync(ApplicationUser user) { var client = _apiService.Client; var qr = await client.GetAuthQRLink(); var trackId = client.AuthStorage.AuthToken.TrackId; var csfrToken = client.AuthStorage.AuthToken.CsfrToken; if (string.IsNullOrEmpty(qr)) throw new Exception("Не удалось получить QR-ссылку"); var cookiesJson = SerializeCookies(_apiService.CookieContainer); var session = new YandexAuthSession { UserId = user.Id, QrCodeUrl = qr, SerializedCookies = cookiesJson, CreatedAt = DateTime.UtcNow, IsConfirmed = false, TrackId = trackId, CsfrToken = csfrToken, }; _dbContext.YandexAuthSessions.Add(session); await _dbContext.SaveChangesAsync(); return new YandexAuthQr { QrLink = qr, SessionId = session.Id.ToString() }; } internal async Task CheckQrAsync(int sessionId) { var session = await _dbContext.YandexAuthSessions.FindAsync(sessionId); if (session == null) return null; RestoreCookies(_apiService.CookieContainer, session.SerializedCookies); if (_apiService.Client.AuthStorage.AuthToken is null) { _apiService.Client.AuthStorage.AuthToken = new(); } _apiService.Client.AuthStorage.AuthToken.CsfrToken = session?.CsfrToken ?? ""; _apiService.Client.AuthStorage.AuthToken.TrackId = session?.TrackId ?? ""; var status = await _apiService.Client.AuthorizeByQR(); if (status?.Status == YAuthStatus.Ok) { session.ConfirmedAt = DateTime.UtcNow; session.IsConfirmed = true; await _dbContext.SaveChangesAsync(); return new() { Status = Shared.Enums.YandexAuthQrStatus.Authorized, }; } return new() { Status = Shared.Enums.YandexAuthQrStatus.Pending, }; } private string SerializeCookies(CookieContainer container) { var domains = new[] { "yandex.ru", "passport.yandex.ru", ".yandex.ru" }; var allCookies = new List(); var cookies = container.GetAllCookies(); foreach (Cookie cookie in cookies) { allCookies.Add(new { cookie.Name, cookie.Value, cookie.Domain, cookie.Path }); } return JsonSerializer.Serialize(allCookies); } private void RestoreCookies(CookieContainer container, string serializedCookies) { var cookies = JsonSerializer.Deserialize>(serializedCookies); foreach (var c in cookies) { var uri = new Uri($"{c.Domain}"); container.Add(uri, new Cookie(c.Name, c.Value, c.Path, c.Domain)); } } private class CookieData { public string Name { get; set; } public string Value { get; set; } public string Domain { get; set; } public string Path { get; set; } } }