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();
}