Полностью переписанное api
All checks were successful
Release / pack-and-publish (release) Successful in 36s
All checks were successful
Release / pack-and-publish (release) Successful in 36s
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
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;
|
||||
@@ -8,143 +6,114 @@ using YandexMusic.API.Requests.Playlist;
|
||||
|
||||
namespace YandexMusic.API;
|
||||
|
||||
/// <summary>API для взаимодействия с плейлистами.</summary>
|
||||
/// <summary>API для работы с плейлистами.</summary>
|
||||
public class YPlaylistAPI : YCommonAPI
|
||||
{
|
||||
/// <summary>Инициализирует новый экземпляр API плейлистов.</summary>
|
||||
/// <param name="yandex">Экземпляр основного API.</param>
|
||||
public YPlaylistAPI(YandexMusicApi yandex) : base(yandex) { }
|
||||
public YPlaylistAPI(YandexMusicApi api) : base(api) { }
|
||||
|
||||
/// <summary>Получает список персональных плейлистов с главной страницы.</summary>
|
||||
/// <param name="storage">Хранилище авторизации.</param>
|
||||
/// <returns>Список ответов с плейлистами.</returns>
|
||||
public async Task<List<YResponse<YPlaylist>>> GetPersonalPlaylistsAsync(AuthStorage storage)
|
||||
public async Task<List<YPlaylist>> GetPersonalPlaylistsAsync()
|
||||
{
|
||||
var landing = await api.Landing.GetAsync(storage, YLandingBlockType.PersonalPlaylists);
|
||||
var block = landing.Result?.Blocks?.FirstOrDefault(b => b.Type == YLandingBlockType.PersonalPlaylists);
|
||||
var landing = await Api.Landing.GetAsync(YLandingBlockType.PersonalPlaylists);
|
||||
var block = landing?.Blocks?.FirstOrDefault(b => b.Type == YLandingBlockType.PersonalPlaylists);
|
||||
if (block?.Entities == null)
|
||||
return new List<YResponse<YPlaylist>>();
|
||||
return new List<YPlaylist>();
|
||||
|
||||
var tasks = block.Entities
|
||||
.OfType<YLandingEntityPersonalPlaylist>()
|
||||
.Select(e => api.Playlist.GetAsync(storage, e.Data?.Data));
|
||||
.Select(e => GetAsync(e.Data?.Data?.Owner?.Uid ?? Api.Storage.User.Uid, e.Data?.Data?.Kind ?? ""))
|
||||
.Where(t => t != null)
|
||||
.ToList();
|
||||
|
||||
return new List<YResponse<YPlaylist>>(await Task.WhenAll(tasks));
|
||||
var results = await Task.WhenAll(tasks);
|
||||
return results.Where(p => p != null).ToList()!;
|
||||
}
|
||||
|
||||
/// <summary>Получает избранные плейлисты.</summary>
|
||||
public Task<YResponse<List<YPlaylist>>> FavoritesAsync(AuthStorage storage)
|
||||
=> new YGetPlaylistFavoritesBuilder(api, storage).Build(null!).GetResponseAsync();
|
||||
public Task<YPlaylist?> GetAsync(string user, string kind)
|
||||
=> new YGetPlaylistBuilder(Api).ExecuteAsync((user, kind));
|
||||
|
||||
/// <summary>Получает плейлист дня.</summary>
|
||||
public Task<YResponse<YPlaylist>> OfTheDayAsync(AuthStorage storage)
|
||||
=> GetPersonalPlaylistAsync(storage, YGeneratedPlaylistType.PlaylistOfTheDay);
|
||||
public Task<YPlaylist?> GetAsync(string uuid)
|
||||
=> new YGetPlaylistByUuidBuilder(Api).ExecuteAsync(uuid);
|
||||
|
||||
/// <summary>Получает плейлист «Дежавю».</summary>
|
||||
public Task<YResponse<YPlaylist>> DejaVuAsync(AuthStorage storage)
|
||||
=> GetPersonalPlaylistAsync(storage, YGeneratedPlaylistType.NeverHeard);
|
||||
public Task<YPlaylist?> GetAsync(YPlaylist playlist)
|
||||
=> GetAsync(playlist.Owner.Uid, playlist.Kind);
|
||||
|
||||
/// <summary>Получает плейлист «Премьера».</summary>
|
||||
public Task<YResponse<YPlaylist>> PremiereAsync(AuthStorage storage)
|
||||
=> GetPersonalPlaylistAsync(storage, YGeneratedPlaylistType.RecentTracks);
|
||||
public Task<List<YPlaylist>?> GetAsync(IEnumerable<(string user, string kind)> ids)
|
||||
=> new YGetPlaylistsBuilder(Api).ExecuteAsync(ids);
|
||||
|
||||
/// <summary>Получает плейлист «Тайник».</summary>
|
||||
public Task<YResponse<YPlaylist>> MissedAsync(AuthStorage storage)
|
||||
=> GetPersonalPlaylistAsync(storage, YGeneratedPlaylistType.MissedLikes);
|
||||
public Task<List<YPlaylist>?> FavoritesAsync()
|
||||
=> new YGetPlaylistFavoritesBuilder(Api).ExecuteAsync(null!);
|
||||
|
||||
/// <summary>Получает плейлист «Кинопоиск».</summary>
|
||||
public Task<YResponse<YPlaylist>> KinopoiskAsync(AuthStorage storage)
|
||||
=> GetPersonalPlaylistAsync(storage, YGeneratedPlaylistType.Kinopoisk);
|
||||
public async Task<YPlaylist?> OfTheDayAsync()
|
||||
=> (await GetPersonalPlaylistsAsync()).FirstOrDefault(p => p?.GeneratedPlaylistType == YGeneratedPlaylistType.PlaylistOfTheDay.ToString());
|
||||
|
||||
private async Task<YResponse<YPlaylist>> 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 async Task<YPlaylist?> DejaVuAsync()
|
||||
=> (await GetPersonalPlaylistsAsync()).FirstOrDefault(p => p?.GeneratedPlaylistType == YGeneratedPlaylistType.NeverHeard.ToString());
|
||||
|
||||
/// <summary>Получает плейлист по идентификатору пользователя и типа.</summary>
|
||||
public Task<YResponse<YPlaylist>> GetAsync(AuthStorage storage, string user, string kind)
|
||||
=> new YGetPlaylistBuilder(api, storage).Build((user, kind)).GetResponseAsync();
|
||||
public async Task<YPlaylist?> PremiereAsync()
|
||||
=> (await GetPersonalPlaylistsAsync()).FirstOrDefault(p => p?.GeneratedPlaylistType == YGeneratedPlaylistType.RecentTracks.ToString());
|
||||
|
||||
/// <summary>Получает плейлист по UUID.</summary>
|
||||
public Task<YResponse<YPlaylist>> GetAsync(AuthStorage storage, string uuid)
|
||||
=> new YGetPlaylistByUuidBuilder(api, storage).Build(uuid).GetResponseAsync();
|
||||
public async Task<YPlaylist?> MissedAsync()
|
||||
=> (await GetPersonalPlaylistsAsync()).FirstOrDefault(p => p?.GeneratedPlaylistType == YGeneratedPlaylistType.MissedLikes.ToString());
|
||||
|
||||
/// <summary>Получает несколько плейлистов по списку пар (пользователь, тип).</summary>
|
||||
public Task<YResponse<List<YPlaylist>>> GetAsync(AuthStorage storage, IEnumerable<(string user, string kind)> ids)
|
||||
=> new YGetPlaylistsBuilder(api, storage).Build(ids).GetResponseAsync();
|
||||
public async Task<YPlaylist?> KinopoiskAsync()
|
||||
=> (await GetPersonalPlaylistsAsync()).FirstOrDefault(p => p?.GeneratedPlaylistType == YGeneratedPlaylistType.Kinopoisk.ToString());
|
||||
|
||||
/// <summary>Получает плейлист по объекту плейлиста (обновляет его треки).</summary>
|
||||
public Task<YResponse<YPlaylist>> GetAsync(AuthStorage storage, YPlaylist playlist)
|
||||
=> new YGetPlaylistBuilder(api, storage).Build((playlist.Owner.Uid, playlist.Kind)).GetResponseAsync();
|
||||
public Task<YPlaylist?> CreateAsync(string name)
|
||||
=> new YPlaylistCreateBuilder(Api).ExecuteAsync(name);
|
||||
|
||||
/// <summary>Создаёт новый плейлист с заданным именем.</summary>
|
||||
public Task<YResponse<YPlaylist>> CreateAsync(AuthStorage storage, string name)
|
||||
=> new YPlaylistCreateBuilder(api, storage).Build(name).GetResponseAsync();
|
||||
public Task<YPlaylist?> RenameAsync(string kind, string name)
|
||||
=> new YPlaylistRenameBuilder(Api).ExecuteAsync((kind, name));
|
||||
|
||||
/// <summary>Переименовывает плейлист.</summary>
|
||||
public Task<YResponse<YPlaylist>> RenameAsync(AuthStorage storage, string kind, string name)
|
||||
=> new YPlaylistRenameBuilder(api, storage).Build((kind, name)).GetResponseAsync();
|
||||
public Task<YPlaylist?> RenameAsync(YPlaylist playlist, string name)
|
||||
=> RenameAsync(playlist.Kind, name);
|
||||
|
||||
/// <summary>Переименовывает плейлист.</summary>
|
||||
public Task<YResponse<YPlaylist>> RenameAsync(AuthStorage storage, YPlaylist playlist, string name)
|
||||
=> RenameAsync(storage, playlist.Kind, name);
|
||||
|
||||
/// <summary>Удаляет плейлист.</summary>
|
||||
public async Task<bool> DeleteAsync(AuthStorage storage, string kind)
|
||||
public async Task<bool> DeleteAsync(string kind)
|
||||
{
|
||||
try
|
||||
{
|
||||
await new YPlaylistRemoveBuilder(api, storage).Build(kind).GetResponseAsync();
|
||||
await new YPlaylistRemoveBuilder(Api).ExecuteAsync(kind);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch
|
||||
{
|
||||
// Логирование ошибки можно добавить через ILogger
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Удаляет плейлист.</summary>
|
||||
public Task<bool> DeleteAsync(AuthStorage storage, YPlaylist playlist)
|
||||
=> DeleteAsync(storage, playlist.Kind);
|
||||
public Task<bool> DeleteAsync(YPlaylist playlist)
|
||||
=> DeleteAsync(playlist.Kind);
|
||||
|
||||
/// <summary>Добавляет треки в начало плейлиста.</summary>
|
||||
public async Task<YResponse<YPlaylist>> InsertTracksAsync(AuthStorage storage, YPlaylist playlist, IEnumerable<YTrack> tracks)
|
||||
public async Task<YPlaylist?> InsertTracksAsync(YPlaylist playlist, IEnumerable<YTrack> tracks)
|
||||
{
|
||||
var change = await ChangePlaylistAsync(storage, playlist, new List<YPlaylistChange>
|
||||
var change = await new YPlaylistChangeBuilder(Api).ExecuteAsync((playlist, new[]
|
||||
{
|
||||
new()
|
||||
new YPlaylistChange
|
||||
{
|
||||
Operation = YPlaylistChangeType.Insert,
|
||||
At = 0,
|
||||
Tracks = tracks.Select(t => t.GetKey())
|
||||
}
|
||||
});
|
||||
return await GetAsync(storage, change.Result);
|
||||
}));
|
||||
return change != null ? await GetAsync(change) : null;
|
||||
}
|
||||
|
||||
/// <summary>Удаляет треки из плейлиста.</summary>
|
||||
public Task<YResponse<YPlaylist>> DeleteTracksAsync(AuthStorage storage, YPlaylist playlist, IEnumerable<YTrack> tracks)
|
||||
public async Task<YPlaylist?> DeleteTracksAsync(YPlaylist playlist, IEnumerable<YTrack> tracks)
|
||||
{
|
||||
var distinctTracks = tracks.Distinct().ToList();
|
||||
|
||||
var changes = distinctTracks
|
||||
var indices = 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<YTrackAlbumPair> { playlist.Tracks![i].Track!.GetKey() }
|
||||
})
|
||||
.ToList();
|
||||
|
||||
return ChangePlaylistAsync(storage, playlist, changes);
|
||||
}
|
||||
var changes = indices.Select(i => new YPlaylistChange
|
||||
{
|
||||
Operation = YPlaylistChangeType.Delete,
|
||||
From = i,
|
||||
To = i + 1,
|
||||
Tracks = new[] { playlist.Tracks![i].Track!.GetKey() }
|
||||
});
|
||||
|
||||
private Task<YResponse<YPlaylist>> ChangePlaylistAsync(AuthStorage storage, YPlaylist playlist, IEnumerable<YPlaylistChange> changes)
|
||||
=> new YPlaylistChangeBuilder(api, storage).Build((playlist, changes)).GetResponseAsync();
|
||||
var change = await new YPlaylistChangeBuilder(Api).ExecuteAsync((playlist, changes));
|
||||
return change != null ? await GetAsync(change) : null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user