using PlaylistShared.Api.Entities; using PlaylistShared.Api.Extensions; using PlaylistShared.Shared.Enums; using PlaylistShared.Shared.Yandex; using YandexMusic.API; using YandexMusic.API.Models.Playlist; using YandexMusic.API.Models.Track; namespace PlaylistShared.Api.Services; public class YandexMusicService { private readonly YandexApiService _yandexApiService; private YandexMusicApi Api => _yandexApiService.Client.Api; private bool IsAuthorized => _yandexApiService.Client.IsAuthorized; public YandexMusicService(YandexApiService yandexApiService) { _yandexApiService = yandexApiService; } private async Task AuthorizeIfNot(ApplicationUser user) { if (!IsAuthorized) { var authResult = await _yandexApiService.AuthAsync(user); if (authResult == null || authResult == false) throw new Exception("Не удалось авторизоваться в Яндекс.Музыке. Проверьте токен."); } } public async Task GetPlaylistAsync(ApplicationUser user, string ownerUid, string kind) { await AuthorizeIfNot(user); return await Api.Playlist.GetAsync(ownerUid, kind); } public async Task CreatePlaylistAsync(ApplicationUser user, string title) { await AuthorizeIfNot(user); return await Api.Playlist.CreateAsync(title); } public async Task AddTracksAsync(ApplicationUser user, string ownerUid, string kind, IEnumerable trackIds) { await AuthorizeIfNot(user); var playlist = await Api.Playlist.GetAsync(ownerUid, kind); if (playlist == null) return null; var tracks = await Api.Track.GetAsync(trackIds); if (tracks == null || !tracks.Any()) return null; var insertedTracks = tracks.Where(t => !playlist.Tracks.Any(p => p.Track.Id == t.Id)).ToArray(); return await playlist.InsertTracksAsync(insertedTracks); } public async Task RemoveTracksAsync(ApplicationUser user, string ownerUid, string kind, IEnumerable trackIds) { await AuthorizeIfNot(user); var tracks = await Api.Track.GetAsync(trackIds); if (tracks == null || !tracks.Any()) return null; var playlist = await Api.Playlist.GetAsync(ownerUid, kind); if (playlist == null) return null; return await playlist.RemoveTracksAsync(tracks.ToArray()); } public async Task GetTrackFileUrlAsync(ApplicationUser user, string trackId) { await AuthorizeIfNot(user); var track = await GetYTrackAsync(user, trackId); if (track == null) return null; return await track.GetLinkAsync(); } public async Task GetYTrackAsync(ApplicationUser user, string trackId) { await AuthorizeIfNot(user); var track = await Api.Track.GetAsync(trackId); return track; } public async Task SearchAsync( ApplicationUser user, string query, TrackSearchType? searchType = TrackSearchType.All, int limit = 20 ) { await AuthorizeIfNot(user); var ySerchType = searchType switch { TrackSearchType.Artist => YandexMusic.API.Models.Common.YSearchType.Artist, TrackSearchType.Album => YandexMusic.API.Models.Common.YSearchType.Album, TrackSearchType.Playlist => YandexMusic.API.Models.Common.YSearchType.Playlist, TrackSearchType.Track => YandexMusic.API.Models.Common.YSearchType.Track, _ => YandexMusic.API.Models.Common.YSearchType.All }; var searchResult = await Api.Search.SearchAsync(query, ySerchType, page: 0, pageSize: limit); if (searchResult?.Tracks?.Results == null) return new YandexSearchResult(); return new YandexSearchResult { Tracks = searchResult.Tracks.Results.Select(t => new YandexTrack { TrackId = t.Id, Title = t.Title, Artists = t.Artists.Select(t => new YandexArtist() { Id = t.Id, Name = t.Name, CoverUrl = t.Cover.GetUrl(), Description = t.Description?.Text ?? string.Empty, }).ToList(), CoverUri = t.CoverUri, DurationMs = t.DurationMs, }).ToList(), Playlists = searchResult.Playlists?.Results.Select(p => new YandexPlaylist { Uuid = p.PlaylistUuid, Kind = p.Kind, OwnerUid = p.Owner?.Uid ?? string.Empty, Title = p.Title, Description = p.Description, CoverUrl = string.IsNullOrEmpty(p.CoverUri) ? p.Cover.GetUrl() : p.CoverUri, TrackCount = p.TrackCount, }).ToList(), Artists = searchResult.Artists?.Results.Select(a => new YandexArtist { Id = a.Id, Name = a.Name, CoverUrl = a.Cover.GetUrl(), Description = a.Description?.Text ?? string.Empty, }).ToList(), Albums = searchResult.Albums?.Results.Select(a => new YandexAlbum { Id = a.Id, Title = a.Title, Artists = a.Artists.Select(t => new YandexArtist() { Id = t.Id, Name = t.Name, CoverUrl = t.Cover.GetUrl(), Description = t.Description?.Text ?? string.Empty, }).ToList(), CoverUrl = string.IsNullOrEmpty(a.CoverUri) ? a.Cover.GetUrl() : a.CoverUri, Description = a.Description, }).ToList(), }; } public async Task SearchTracksByIdAsync( ApplicationUser user, string id, TrackSearchType searchType, int limit = 20 ) { YandexSearchResult result = new(); await AuthorizeIfNot(user); if (searchType == TrackSearchType.All) { throw new Exception("Для поиска по ID необходимо указать конкретный тип (трек, альбом, исполнитель или плейлист)."); } else if (searchType == TrackSearchType.Track) { var track = await Api.Track.GetAsync(id); if (track != null) { result.Tracks = new List() { new() { TrackId = track.Id, Title = track.Title, Artists = track.Artists.Select(t => new YandexArtist() { Id = t.Id, Name = t.Name, CoverUrl = t.Cover.GetUrl(), Description = t.Description?.Text ?? string.Empty, }).ToList(), CoverUri = track.CoverUri ?? string.Empty, DurationMs = track.DurationMs, } }; } } else if (searchType == TrackSearchType.Album) { var album = await Api.Album.GetAsync(id); result.Tracks = album?.Volumes.SelectMany(v => v).Select(t => new YandexTrack { TrackId = t.Id, Title = t.Title, Artists = t.Artists.Select(t => new YandexArtist() { Id = t.Id, Name = t.Name, CoverUrl = t.Cover.GetUrl(), Description = t.Description?.Text ?? string.Empty, }).ToList(), CoverUri = t.CoverUri ?? string.Empty, DurationMs = t.DurationMs, }).ToList(); } else if (searchType == TrackSearchType.Artist) { var artist = await Api.Artist.GetAsync(id); if (artist != null) { result.Albums = artist.Albums.Select(a => new YandexAlbum() { Id = a.Id, Title = a.Title, Artists = a.Artists.Select(t => new YandexArtist() { Id = t.Id, Name = t.Name, CoverUrl = t.Cover.GetUrl(), Description = t.Description?.Text ?? string.Empty, }).ToList(), CoverUrl = string.IsNullOrEmpty(a.CoverUri) ? a.Cover.GetUrl() : a.CoverUri, Description = a.Description, }).ToList(); result.Playlists = artist.Playlists.Select(p => new YandexPlaylist { Uuid = p.PlaylistUuid, Kind = p.Kind, OwnerUid = p.Owner?.Uid ?? string.Empty, Title = p.Title, Description = p.Description, CoverUrl = p.Cover.GetUrl(), TrackCount = p.TrackCount, }).ToList(); result.Tracks = artist.PopularTracks.Select(t => new YandexTrack { TrackId = t.Id, Title = t.Title, Artists = t.Artists.Select(a => new YandexArtist() { Id = a.Id, Name = a.Name, CoverUrl = a.Cover.GetUrl(), Description = a.Description?.Text ?? string.Empty, }).ToList(), CoverUri = t.CoverUri ?? string.Empty, DurationMs = t.DurationMs, }).ToList(); } } else if (searchType == TrackSearchType.Playlist) { var playlist = await Api.Playlist.GetAsync(id); result.Tracks = playlist?.Tracks.Select(p => new YandexTrack { TrackId = p.Track.Id, CoverUri = p.Track.CoverUri, Artists = p.Track.Artists.Select(a => new YandexArtist { Id = a.Id, Name = a.Name, CoverUrl = a.Cover.GetUrl(), Description = a.Description?.Text ?? string.Empty, }).ToList(), Title = p.Track.Title, DurationMs = p.Track.DurationMs, }).ToList(); } return result; } }