using YandexMusic.API.Common; using YandexMusic.API.Models.Common; using YandexMusic.API.Models.Landing; using YandexMusic.API.Models.Landing.Entity.Entities; using YandexMusic.API.Models.Playlist; using YandexMusic.API.Models.Track; using YandexMusic.API.Requests.Playlist; namespace YandexMusic.API; /// API для взаимодействия с плейлистами. public class YPlaylistAPI : YCommonAPI { /// Инициализирует новый экземпляр API плейлистов. /// Экземпляр основного API. public YPlaylistAPI(YandexMusicApi yandex) : base(yandex) { } /// Получает список персональных плейлистов с главной страницы. /// Хранилище авторизации. /// Список ответов с плейлистами. public async Task>> GetPersonalPlaylistsAsync(AuthStorage storage) { var landing = await api.Landing.GetAsync(storage, YLandingBlockType.PersonalPlaylists); var block = landing.Result?.Blocks?.FirstOrDefault(b => b.Type == YLandingBlockType.PersonalPlaylists); if (block?.Entities == null) return new List>(); var tasks = block.Entities .OfType() .Select(e => api.Playlist.GetAsync(storage, e.Data?.Data)); return new List>(await Task.WhenAll(tasks)); } /// Получает избранные плейлисты. public Task>> FavoritesAsync(AuthStorage storage) => new YGetPlaylistFavoritesBuilder(api, storage).Build(null!).GetResponseAsync(); /// Получает плейлист дня. public Task> OfTheDayAsync(AuthStorage storage) => GetPersonalPlaylistAsync(storage, YGeneratedPlaylistType.PlaylistOfTheDay); /// Получает плейлист «Дежавю». public Task> DejaVuAsync(AuthStorage storage) => GetPersonalPlaylistAsync(storage, YGeneratedPlaylistType.NeverHeard); /// Получает плейлист «Премьера». public Task> PremiereAsync(AuthStorage storage) => GetPersonalPlaylistAsync(storage, YGeneratedPlaylistType.RecentTracks); /// Получает плейлист «Тайник». public Task> MissedAsync(AuthStorage storage) => GetPersonalPlaylistAsync(storage, YGeneratedPlaylistType.MissedLikes); /// Получает плейлист «Кинопоиск». public Task> KinopoiskAsync(AuthStorage storage) => GetPersonalPlaylistAsync(storage, YGeneratedPlaylistType.Kinopoisk); private async Task> GetPersonalPlaylistAsync(AuthStorage storage, YGeneratedPlaylistType type) { var list = await GetPersonalPlaylistsAsync(storage); return list.FirstOrDefault(e => string.Equals(e.Result?.GeneratedPlaylistType, type.ToString(), StringComparison.CurrentCultureIgnoreCase)) ?? throw new Exception($"Плейлист типа {type} не найден."); } /// Получает плейлист по идентификатору пользователя и типа. public Task> GetAsync(AuthStorage storage, string user, string kind) => new YGetPlaylistBuilder(api, storage).Build((user, kind)).GetResponseAsync(); /// Получает плейлист по UUID. public Task> GetAsync(AuthStorage storage, string uuid) => new YGetPlaylistByUuidBuilder(api, storage).Build(uuid).GetResponseAsync(); /// Получает несколько плейлистов по списку пар (пользователь, тип). public Task>> GetAsync(AuthStorage storage, IEnumerable<(string user, string kind)> ids) => new YGetPlaylistsBuilder(api, storage).Build(ids).GetResponseAsync(); /// Получает плейлист по объекту плейлиста (обновляет его треки). public Task> GetAsync(AuthStorage storage, YPlaylist playlist) => new YGetPlaylistBuilder(api, storage).Build((playlist.Owner.Uid, playlist.Kind)).GetResponseAsync(); /// Создаёт новый плейлист с заданным именем. public Task> CreateAsync(AuthStorage storage, string name) => new YPlaylistCreateBuilder(api, storage).Build(name).GetResponseAsync(); /// Переименовывает плейлист. public Task> RenameAsync(AuthStorage storage, string kind, string name) => new YPlaylistRenameBuilder(api, storage).Build((kind, name)).GetResponseAsync(); /// Переименовывает плейлист. public Task> RenameAsync(AuthStorage storage, YPlaylist playlist, string name) => RenameAsync(storage, playlist.Kind, name); /// Удаляет плейлист. public async Task DeleteAsync(AuthStorage storage, string kind) { try { await new YPlaylistRemoveBuilder(api, storage).Build(kind).GetResponseAsync(); return true; } catch (Exception ex) { // Логирование ошибки можно добавить через ILogger return false; } } /// Удаляет плейлист. public Task DeleteAsync(AuthStorage storage, YPlaylist playlist) => DeleteAsync(storage, playlist.Kind); /// Добавляет треки в начало плейлиста. public async Task> InsertTracksAsync(AuthStorage storage, YPlaylist playlist, IEnumerable tracks) { var change = await ChangePlaylistAsync(storage, playlist, new List { new() { Operation = YPlaylistChangeType.Insert, At = 0, Tracks = tracks.Select(t => t.GetKey()) } }); return await GetAsync(storage, change.Result); } /// Удаляет треки из плейлиста. public Task> DeleteTracksAsync(AuthStorage storage, YPlaylist playlist, IEnumerable tracks) { var distinctTracks = tracks.Distinct().ToList(); var changes = distinctTracks .Select(t => playlist.Tracks?.FindIndex(ct => ct.Track?.GetKey() == t.GetKey()) ?? -1) .Where(i => i != -1) .Select(i => new YPlaylistChange { Operation = YPlaylistChangeType.Delete, From = i, To = i + 1, Tracks = new List { playlist.Tracks![i].Track!.GetKey() } }) .ToList(); return ChangePlaylistAsync(storage, playlist, changes); } private Task> ChangePlaylistAsync(AuthStorage storage, YPlaylist playlist, IEnumerable changes) => new YPlaylistChangeBuilder(api, storage).Build((playlist, changes)).GetResponseAsync(); }