Добавьте файлы проекта.
This commit is contained in:
38
YandexMusic.API/API/YAlbumAPI.cs
Normal file
38
YandexMusic.API/API/YAlbumAPI.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Album;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Requests.Album;
|
||||
|
||||
namespace YandexMusic.API;
|
||||
|
||||
/// <summary>
|
||||
/// API для взаимодействия с альбомами
|
||||
/// </summary>
|
||||
public class YAlbumAPI : YCommonAPI
|
||||
{
|
||||
public YAlbumAPI(YandexMusicApi yandex) : base(yandex)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Получает альбом по идентификатору.</summary>
|
||||
/// <param name="storage">Хранилище авторизации.</param>
|
||||
/// <param name="albumId">Идентификатор альбома.</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YAlbum>> GetAsync(AuthStorage storage, string albumId)
|
||||
{
|
||||
return new YGetAlbumBuilder(api, storage)
|
||||
.Build(albumId)
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>Получение альбомов по списку идентификаторов.</summary>
|
||||
/// <param name="storage">Хранилище авторизации.</param>
|
||||
/// <param name="albumIds">Идентификаторы альбомов.</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<List<YAlbum>>> GetAsync(AuthStorage storage, IEnumerable<string> albumIds)
|
||||
{
|
||||
return new YGetAlbumsBuilder(api, storage)
|
||||
.Build(albumIds)
|
||||
.GetResponseAsync();
|
||||
}
|
||||
}
|
||||
71
YandexMusic.API/API/YArtistAPI.cs
Normal file
71
YandexMusic.API/API/YArtistAPI.cs
Normal file
@@ -0,0 +1,71 @@
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Artist;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Requests.Artist;
|
||||
|
||||
namespace YandexMusic.API;
|
||||
|
||||
/// <summary>
|
||||
/// API для взаимодействия с исполнителями
|
||||
/// </summary>
|
||||
public class YArtistAPI : YCommonAPI
|
||||
{
|
||||
public YArtistAPI(YandexMusicApi yandex) : base(yandex)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение исполнителя
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="artistId">Идентификатор</param>
|
||||
public Task<YResponse<YArtistBriefInfo>> GetAsync(AuthStorage storage, string artistId)
|
||||
{
|
||||
return new YGetArtistBuilder(api, storage)
|
||||
.Build(artistId)
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение исполнителей
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="artistIds">Идентификаторы</param>
|
||||
public Task<YResponse<List<YArtist>>> GetAsync(AuthStorage storage, IEnumerable<string> artistIds)
|
||||
{
|
||||
return new YGetArtistsBuilder(api, storage)
|
||||
.Build(artistIds)
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение треков исполнителя с пагинацией
|
||||
/// <remarks>
|
||||
/// Треки поставляются по <paramref name="pageSize"/> штук на страницу,
|
||||
/// для получения всех треков необходимо использовать метод <see cref="GetAllTracksAsync"/>
|
||||
/// </remarks>
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="artistId">Идентификатор исполнителя</param>
|
||||
/// <param name="page">Страница ответов</param>
|
||||
/// <param name="pageSize">Количество треков на странице ответов</param>
|
||||
public Task<YResponse<YTracksPage>> GetTracksAsync(AuthStorage storage, string artistId, int page = 0, int pageSize = 20)
|
||||
{
|
||||
return new YGetArtistTrackBuilder(api, storage)
|
||||
.Build((artistId, page, pageSize))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение всех треков исполнителя
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="artistId">Идентификатор исполнителя</param>
|
||||
public async Task<YResponse<YTracksPage>> GetAllTracksAsync(AuthStorage storage, string artistId)
|
||||
{
|
||||
YResponse<YArtistBriefInfo> response = await GetAsync(storage, artistId);
|
||||
return await GetTracksAsync(storage, artistId, pageSize: response.Result.Artist.Counts.Tracks);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
14
YandexMusic.API/API/YCommonAPI.cs
Normal file
14
YandexMusic.API/API/YCommonAPI.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace YandexMusic.API;
|
||||
|
||||
/// <summary>
|
||||
/// Родительский класс для ветки API
|
||||
/// </summary>
|
||||
public class YCommonAPI
|
||||
{
|
||||
protected YandexMusicApi api;
|
||||
|
||||
public YCommonAPI(YandexMusicApi yandex)
|
||||
{
|
||||
api = yandex;
|
||||
}
|
||||
}
|
||||
40
YandexMusic.API/API/YLabelAPIAsync.cs
Normal file
40
YandexMusic.API/API/YLabelAPIAsync.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Label;
|
||||
using YandexMusic.API.Requests.Label;
|
||||
|
||||
namespace YandexMusic.API
|
||||
{
|
||||
public partial class YLabelAPI : YCommonAPI
|
||||
{
|
||||
public YLabelAPI(YandexMusicApi yandex) : base(yandex)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Постраничное получение альбомов лейбла
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="label">Лейбл</param>
|
||||
/// <param name="page">Страница</param>
|
||||
public Task<YResponse<YLabelAlbums>> GetAlbumsByLabelAsync(AuthStorage storage, YLabel label, int page)
|
||||
{
|
||||
return new YGetLabelAlbumsBuilder(api, storage)
|
||||
.Build((label, page))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Постраничное получение артистов лейбла
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="label">Лейбл</param>
|
||||
/// <param name="page">Страница</param>
|
||||
public Task<YResponse<YLabelArtists>> GetArtistsByLabelAsync(AuthStorage storage, YLabel label, int page)
|
||||
{
|
||||
return new YGetLabelArtistsBuilder(api, storage)
|
||||
.Build((label, page))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
63
YandexMusic.API/API/YLandingAPIAsync.cs
Normal file
63
YandexMusic.API/API/YLandingAPIAsync.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Feed;
|
||||
using YandexMusic.API.Models.Landing;
|
||||
using YandexMusic.API.Requests.Feed;
|
||||
using YandexMusic.API.Requests.Landing;
|
||||
|
||||
namespace YandexMusic.API
|
||||
{
|
||||
/// <summary>
|
||||
/// API для взаимодействия с главной страницей
|
||||
/// </summary>
|
||||
public partial class YLandingAPI : YCommonAPI
|
||||
{
|
||||
|
||||
|
||||
public YLandingAPI(YandexMusicApi yandex) : base(yandex)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение персональных списков
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="blocks">Типы запрашиваемых блоков</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YLanding>> GetAsync(AuthStorage storage, params YLandingBlockType[] blocks)
|
||||
{
|
||||
if (blocks == null)
|
||||
return null;
|
||||
|
||||
return new YGetLandingBuilder(api, storage)
|
||||
.Build(blocks)
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение ленты
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YFeed>> GetFeedAsync(AuthStorage storage)
|
||||
{
|
||||
return new YGetFeedBuilder(api, storage)
|
||||
.Build(null)
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение лендинга детского раздела
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YChildrenLanding>> GetChildrenLandingAsync(AuthStorage storage)
|
||||
{
|
||||
return new YGetChildrenLandingBuilder(api, storage)
|
||||
.Build(null)
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
258
YandexMusic.API/API/YLibraryAPIAsync.cs
Normal file
258
YandexMusic.API/API/YLibraryAPIAsync.cs
Normal file
@@ -0,0 +1,258 @@
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Album;
|
||||
using YandexMusic.API.Models.Artist;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Landing.Entity.Entities.Context;
|
||||
using YandexMusic.API.Models.Library;
|
||||
using YandexMusic.API.Models.Playlist;
|
||||
using YandexMusic.API.Models.Track;
|
||||
using YandexMusic.API.Requests.Library;
|
||||
|
||||
namespace YandexMusic.API
|
||||
{
|
||||
/// <summary>
|
||||
/// API для взаимодействия с библиотекой
|
||||
/// </summary>
|
||||
public partial class YLibraryAPI : YCommonAPI
|
||||
{
|
||||
#region Вспомогательные функции
|
||||
|
||||
/// <summary>
|
||||
/// Получение секции библиотеки
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Тип объекта библиотеки</typeparam>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="section">Секция</param>
|
||||
/// <param name="type">Тип</param>
|
||||
/// <returns>Список объектов из секции</returns>
|
||||
private Task<YResponse<T>> GetLibrarySection<T>(AuthStorage storage, YLibrarySection section, YLibrarySectionType type = YLibrarySectionType.Likes)
|
||||
{
|
||||
return new YGetLibrarySectionBuilder<T>(api, storage)
|
||||
.Build((section, type))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
#endregion Вспомогательные функции
|
||||
|
||||
|
||||
|
||||
public YLibraryAPI(YandexMusicApi yandex) : base(yandex)
|
||||
{
|
||||
}
|
||||
|
||||
#region Лайки
|
||||
|
||||
/// <summary>
|
||||
/// Получение лайкнутых треков
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YLibraryTracks>> GetLikedTracksAsync(AuthStorage storage)
|
||||
{
|
||||
return GetLibrarySection<YLibraryTracks>(storage, YLibrarySection.Tracks);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение лайкнутых альбомов
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<List<YLibraryAlbum>>> GetLikedAlbumsAsync(AuthStorage storage)
|
||||
{
|
||||
return GetLibrarySection<List<YLibraryAlbum>>(storage, YLibrarySection.Albums);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение лайкнутых исполнителей
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<List<YArtist>>> GetLikedArtistsAsync(AuthStorage storage)
|
||||
{
|
||||
return GetLibrarySection<List<YArtist>>(storage, YLibrarySection.Artists);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение лайкнутых плейлистов
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<List<YLibraryPlaylists>>> GetLikedPlaylistsAsync(AuthStorage storage)
|
||||
{
|
||||
return GetLibrarySection<List<YLibraryPlaylists>>(storage, YLibrarySection.Playlists);
|
||||
}
|
||||
|
||||
#endregion Лайки
|
||||
|
||||
#region Дизлайки
|
||||
|
||||
/// <summary>
|
||||
/// Получение дизлайкнутых треков
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YLibraryTracks>> GetDislikedTracksAsync(AuthStorage storage)
|
||||
{
|
||||
return GetLibrarySection<YLibraryTracks>(storage, YLibrarySection.Tracks, YLibrarySectionType.Dislikes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение дизлайкнутых исполнителей
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<List<YArtist>>> GetDislikedArtistsAsync(AuthStorage storage)
|
||||
{
|
||||
return GetLibrarySection<List<YArtist>>(storage, YLibrarySection.Artists, YLibrarySectionType.Dislikes);
|
||||
}
|
||||
|
||||
#endregion Дизлайки
|
||||
|
||||
#region Добавление в списки лайков/дизлайков
|
||||
|
||||
/// <summary>
|
||||
/// Добавить трек в список лайкнутых
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="track">Трек</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YPlaylist>> AddTrackLikeAsync(AuthStorage storage, YTrack track)
|
||||
{
|
||||
return new YLibraryAddBuilder<YPlaylist>(api, storage)
|
||||
.Build((track.GetKey().ToString(), YLibrarySection.Tracks, YLibrarySectionType.Likes))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удалить трек из списка лайкнутых
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="track">Трек</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YRevision>> RemoveTrackLikeAsync(AuthStorage storage, YTrack track)
|
||||
{
|
||||
return new YLibraryRemoveBuilder<YRevision>(api, storage)
|
||||
.Build((track.GetKey().ToString(), YLibrarySection.Tracks, YLibrarySectionType.Likes))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Добавить трек в список дизлайкнутых
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="track">Трек</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YRevision>> AddTrackDislikeAsync(AuthStorage storage, YTrack track)
|
||||
{
|
||||
return new YLibraryAddBuilder<YRevision>(api, storage)
|
||||
.Build((track.GetKey().ToString(), YLibrarySection.Tracks, YLibrarySectionType.Dislikes))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удалить трек из списка дизлайкнутых
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="track">Трек</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YRevision>> RemoveTrackDislikeAsync(AuthStorage storage, YTrack track)
|
||||
{
|
||||
return new YLibraryRemoveBuilder<YRevision>(api, storage)
|
||||
.Build((track.GetKey().ToString(), YLibrarySection.Tracks, YLibrarySectionType.Dislikes))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Добавить альбом в список лайкнутых
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="album">Альбом</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<string>> AddAlbumLikeAsync(AuthStorage storage, YAlbum album)
|
||||
{
|
||||
return new YLibraryAddBuilder<string>(api, storage)
|
||||
.Build((album.Id, YLibrarySection.Albums, YLibrarySectionType.Likes))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удалить альбом из списка лайкнутых
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="album">Альбом</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<string>> RemoveAlbumLikeAsync(AuthStorage storage, YAlbum album)
|
||||
{
|
||||
return new YLibraryRemoveBuilder<string>(api, storage)
|
||||
.Build((album.Id, YLibrarySection.Albums, YLibrarySectionType.Likes))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Добавить исполнителя в список лайкнутых
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="artist">Исполнитель</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<string>> AddArtistLikeAsync(AuthStorage storage, YArtist artist)
|
||||
{
|
||||
return new YLibraryAddBuilder<string>(api, storage)
|
||||
.Build((artist.Id, YLibrarySection.Artists, YLibrarySectionType.Likes))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удалить исполнителя из списка лайкнутых
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="artist">Исполнитель</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<string>> RemoveArtistLikeAsync(AuthStorage storage, YArtist artist)
|
||||
{
|
||||
return new YLibraryRemoveBuilder<string>(api, storage)
|
||||
.Build((artist.Id, YLibrarySection.Artists, YLibrarySectionType.Likes))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Добавить плейлист в список лайкнутых
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="playlist">Плейлист</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<string>> AddPlaylistLikeAsync(AuthStorage storage, YPlaylist playlist)
|
||||
{
|
||||
return new YLibraryAddBuilder<string>(api, storage)
|
||||
.Build((playlist.GetKey().ToString(), YLibrarySection.Playlists, YLibrarySectionType.Likes))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удалить плейлист из списка лайкнутых
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="playlist">Плейлист</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<string>> RemovePlaylistLikeAsync(AuthStorage storage, YPlaylist playlist)
|
||||
{
|
||||
return new YLibraryRemoveBuilder<string>(api, storage)
|
||||
.Build((playlist.GetKey().ToString(), YLibrarySection.Playlists, YLibrarySectionType.Likes))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
#endregion Добавление/удаление в списки лайков/дизлайков
|
||||
|
||||
#region Получение списка "Вы недавно слушали"
|
||||
|
||||
public Task<YResponse<YRecentlyListenedContext>> GetRecentlyListenedAsync(AuthStorage storage, IEnumerable<YPlayContextType> contextTypes, int trackCount, int contextCount)
|
||||
{
|
||||
return new YGetLibraryRecentlyListenedBuilder(api, storage)
|
||||
.Build((contextTypes, trackCount, contextCount))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
#endregion Получение списка "Вы недавно слушали"
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
33
YandexMusic.API/API/YPinsAPIAsync.cs
Normal file
33
YandexMusic.API/API/YPinsAPIAsync.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Pins;
|
||||
using YandexMusic.API.Requests.Pins;
|
||||
|
||||
namespace YandexMusic.API
|
||||
{
|
||||
/// <summary>
|
||||
/// API для взаимодействия с прикреплёнными объектами
|
||||
/// </summary>
|
||||
public partial class YPinsAPI : YCommonAPI
|
||||
{
|
||||
|
||||
|
||||
public YPinsAPI(YandexMusicApi yandex) : base(yandex)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение списка прикреплённых объектов
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YPins>> GetAsync(AuthStorage storage)
|
||||
{
|
||||
return new YGetPinsBuilder(api, storage)
|
||||
.Build(null)
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
335
YandexMusic.API/API/YPlaylistAPIAsync.cs
Normal file
335
YandexMusic.API/API/YPlaylistAPIAsync.cs
Normal file
@@ -0,0 +1,335 @@
|
||||
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
|
||||
{
|
||||
/// <summary>
|
||||
/// API для взамодействия с плейлистами
|
||||
/// </summary>
|
||||
public partial class YPlaylistAPI : YCommonAPI
|
||||
{
|
||||
#region Вспомогательные функции
|
||||
|
||||
/// <summary>
|
||||
/// Получение персональных плейлистов
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="type">Тип</param>
|
||||
/// <returns>Плейлист</returns>
|
||||
private async Task<YResponse<YPlaylist>> GetPersonalPlaylist(AuthStorage storage, YGeneratedPlaylistType type)
|
||||
{
|
||||
List<YResponse<YPlaylist>> list = await GetPersonalPlaylistsAsync(storage);
|
||||
return list.FirstOrDefault(e => string.Equals(e.Result.GeneratedPlaylistType, type.ToString(), StringComparison.CurrentCultureIgnoreCase));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Изменение плейлиста
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="playlist">Плейлист</param>
|
||||
/// <param name="changes">Список изменений</param>
|
||||
/// <returns>Плейлист после изменений</returns>
|
||||
private Task<YResponse<YPlaylist>> ChangePlaylist(AuthStorage storage, YPlaylist playlist, IEnumerable<YPlaylistChange> changes)
|
||||
{
|
||||
return new YPlaylistChangeBuilder(api, storage)
|
||||
.Build((playlist, changes))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
private IEnumerable<YTrack> RemoveIdentical(IEnumerable<YTrack> tracks)
|
||||
{
|
||||
return tracks.Distinct();
|
||||
}
|
||||
|
||||
#endregion Вспомогательные функции
|
||||
|
||||
|
||||
|
||||
public YPlaylistAPI(YandexMusicApi yandex) : base(yandex)
|
||||
{
|
||||
}
|
||||
|
||||
#region Список с главной
|
||||
|
||||
/// <summary>
|
||||
/// Получение списка персональных плейлистов
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<YResponse<YPlaylist>>> GetPersonalPlaylistsAsync(AuthStorage storage)
|
||||
{
|
||||
YResponse<YLanding> landing = await api.Landing.GetAsync(storage, YLandingBlockType.PersonalPlaylists);
|
||||
|
||||
IEnumerable<Task<YResponse<YPlaylist>>> tasks = landing
|
||||
.Result
|
||||
.Blocks
|
||||
.FirstOrDefault(b => b.Type == YLandingBlockType.PersonalPlaylists)
|
||||
?.Entities
|
||||
.Select(e => api.Playlist.GetAsync(storage, ((YLandingEntityPersonalPlaylist)e).Data?.Data));
|
||||
|
||||
return tasks == null
|
||||
? new List<YResponse<YPlaylist>>()
|
||||
: new List<YResponse<YPlaylist>>(await Task.WhenAll(tasks));
|
||||
}
|
||||
|
||||
#endregion Список с главной
|
||||
|
||||
#region Стандартные плейлисты
|
||||
|
||||
/// <summary>
|
||||
/// Избранное
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<List<YPlaylist>>> FavoritesAsync(AuthStorage storage)
|
||||
{
|
||||
return new YGetPlaylistFavoritesBuilder(api, storage)
|
||||
.Build(null)
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Плейлист дня
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YPlaylist>> OfTheDayAsync(AuthStorage storage)
|
||||
{
|
||||
return GetPersonalPlaylist(storage, YGeneratedPlaylistType.PlaylistOfTheDay);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Дежавю
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YPlaylist>> DejaVuAsync(AuthStorage storage)
|
||||
{
|
||||
return GetPersonalPlaylist(storage, YGeneratedPlaylistType.NeverHeard);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Премьера
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YPlaylist>> PremiereAsync(AuthStorage storage)
|
||||
{
|
||||
return GetPersonalPlaylist(storage, YGeneratedPlaylistType.RecentTracks);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Тайник
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YPlaylist>> MissedAsync(AuthStorage storage)
|
||||
{
|
||||
return GetPersonalPlaylist(storage, YGeneratedPlaylistType.MissedLikes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Кинопоиск
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YPlaylist>> KinopoiskAsync(AuthStorage storage)
|
||||
{
|
||||
return GetPersonalPlaylist(storage, YGeneratedPlaylistType.Kinopoisk);
|
||||
}
|
||||
|
||||
#endregion Стандартные плейлисты
|
||||
|
||||
#region Получение плейлиста
|
||||
|
||||
/// <summary>
|
||||
/// Получение плейлиста
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="user">Uid пользователя-владельца плейлиста</param>
|
||||
/// <param name="kind">Тип</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YPlaylist>> GetAsync(AuthStorage storage, string user, string kind)
|
||||
{
|
||||
return new YGetPlaylistBuilder(api, storage)
|
||||
.Build((user, kind))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение плейлиста по uuid
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="uuid">uuid</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YPlaylist>> GetAsync(AuthStorage storage, string uuid)
|
||||
{
|
||||
return new YGetPlaylistByUuidBuilder(api, storage)
|
||||
.Build(uuid)
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение плейлистов
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="ids">Список пар пользователь:тип</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<List<YPlaylist>>> GetAsync(AuthStorage storage, IEnumerable<(string user, string kind)> ids)
|
||||
{
|
||||
return new YGetPlaylistsBuilder(api, storage)
|
||||
.Build(ids)
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение плейлиста
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="playlist">Описание плейлиста, для которого будут запрошены треки</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YPlaylist>> GetAsync(AuthStorage storage, YPlaylist playlist)
|
||||
{
|
||||
return new YGetPlaylistBuilder(api, storage)
|
||||
.Build((playlist.Owner.Uid, playlist.Kind))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
#endregion Получение плейлиста
|
||||
|
||||
#region Операции над плейлистами
|
||||
|
||||
/// <summary>
|
||||
/// Создание
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="name">Заголовок</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YPlaylist>> CreateAsync(AuthStorage storage, string name)
|
||||
{
|
||||
return new YPlaylistCreateBuilder(api, storage)
|
||||
.Build(name)
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Переименование
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="kinds">Идентификатор плейлиста</param>
|
||||
/// <param name="name">Заголовок</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YPlaylist>> RenameAsync(AuthStorage storage, string kinds, string name)
|
||||
{
|
||||
return new YPlaylistRenameBuilder(api, storage)
|
||||
.Build((kinds, name))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Переименование
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="playlist">Плейлист</param>
|
||||
/// <param name="name">Заголовок</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YPlaylist>> RenameAsync(AuthStorage storage, YPlaylist playlist, string name)
|
||||
{
|
||||
return RenameAsync(storage, playlist.Kind, name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удаление
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="kinds">Тип</param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> DeleteAsync(AuthStorage storage, string kinds)
|
||||
{
|
||||
try
|
||||
{
|
||||
await new YPlaylistRemoveBuilder(api, storage)
|
||||
.Build(kinds)
|
||||
.GetResponseAsync();
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удаление
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="playlist">Плейлист</param>
|
||||
/// <returns></returns>
|
||||
public Task<bool> DeleteAsync(AuthStorage storage, YPlaylist playlist)
|
||||
{
|
||||
return DeleteAsync(storage, playlist.Kind);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Добавление трека
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="playlist">Плейлист</param>
|
||||
/// <param name="tracks">Треки для добавления</param>
|
||||
/// <returns></returns>
|
||||
public async Task<YResponse<YPlaylist>> InsertTracksAsync(AuthStorage storage, YPlaylist playlist, IEnumerable<YTrack> tracks)
|
||||
{
|
||||
YResponse<YPlaylist> change = await ChangePlaylist(storage, playlist, new List<YPlaylistChange> {
|
||||
new() {
|
||||
Operation = YPlaylistChangeType.Insert,
|
||||
At = 0,
|
||||
Tracks = tracks.Select(t => t.GetKey())
|
||||
}
|
||||
});
|
||||
|
||||
return await GetAsync(storage, change.Result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Удаление треков
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="playlist">Плейлист</param>
|
||||
/// <param name="tracks">Треки для удаления</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YPlaylist>> DeleteTracksAsync(AuthStorage storage, YPlaylist playlist, IEnumerable<YTrack> tracks)
|
||||
{
|
||||
List<YPlaylistChange> changes = RemoveIdentical(tracks)
|
||||
.Select(t => playlist.Tracks.Select(c => c.Track).ToList().IndexOf(t))
|
||||
.Where(i => i != -1)
|
||||
.Select(i =>
|
||||
{
|
||||
YTrackContainer t = playlist.Tracks[i];
|
||||
return new YPlaylistChange
|
||||
{
|
||||
Operation = YPlaylistChangeType.Delete,
|
||||
From = i,
|
||||
To = i + 1,
|
||||
Tracks = new List<YTrackAlbumPair> {
|
||||
t.Track.GetKey()
|
||||
}
|
||||
};
|
||||
})
|
||||
.ToList();
|
||||
|
||||
return ChangePlaylist(storage, playlist, changes);
|
||||
}
|
||||
|
||||
#endregion Операции над плейлистами
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
73
YandexMusic.API/API/YQueueAPIAsync.cs
Normal file
73
YandexMusic.API/API/YQueueAPIAsync.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Queue;
|
||||
using YandexMusic.API.Requests.Queue;
|
||||
|
||||
namespace YandexMusic.API
|
||||
{
|
||||
/// <summary>
|
||||
/// API для взаимодействия с очередями
|
||||
/// </summary>
|
||||
public partial class YQueueAPI : YCommonAPI
|
||||
{
|
||||
public YQueueAPI(YandexMusicApi yandex) : base(yandex)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение всех очередей треков с разных устройств для синхронизации между ними
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="device">Устройство</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YQueueItemsContainer>> ListAsync(AuthStorage storage, string device = null)
|
||||
{
|
||||
return new YQueuesListBuilder(api, storage)
|
||||
.Build(device)
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение очереди
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="queueId">Идентификатор очереди</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YQueue>> GetAsync(AuthStorage storage, string queueId)
|
||||
{
|
||||
return new YGetQueueBuilder(api, storage)
|
||||
.Build(queueId)
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Создание новой очереди треков
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="queue">Очередь треков</param>
|
||||
/// <param name="device">Устройство</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YNewQueue>> CreateAsync(AuthStorage storage, YQueue queue, string device = null)
|
||||
{
|
||||
return new YQueueCreateBuilder(api, storage, device)
|
||||
.Build(queue)
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Установка текущего индекса проигрываемого трека в очереди треков
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="queueId">Идентификатор очереди</param>
|
||||
/// <param name="currentIndex">Текущий индекс</param>
|
||||
/// <param name="isInteractive">Флаг интерактивности</param>
|
||||
/// <param name="device">Устройство</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YUpdatedQueue>> UpdatePositionAsync(AuthStorage storage, string queueId, int currentIndex, bool isInteractive, string device = null)
|
||||
{
|
||||
return new YQueueUpdatePositionBuilder(api, storage, device)
|
||||
.Build((queueId, currentIndex, isInteractive))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
116
YandexMusic.API/API/YRadioAPIAsync.cs
Normal file
116
YandexMusic.API/API/YRadioAPIAsync.cs
Normal file
@@ -0,0 +1,116 @@
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Radio;
|
||||
using YandexMusic.API.Models.Track;
|
||||
using YandexMusic.API.Requests.Radio;
|
||||
|
||||
namespace YandexMusic.API
|
||||
{
|
||||
/// <summary>
|
||||
/// API для взаимодействия с радио
|
||||
/// </summary>
|
||||
public partial class YRadioAPI : YCommonAPI
|
||||
{
|
||||
|
||||
|
||||
public YRadioAPI(YandexMusicApi yandex) : base(yandex)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение списка рекомендованных радиостанций
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YStationsDashboard>> GetStationsDashboardAsync(AuthStorage storage)
|
||||
{
|
||||
return new YGetStationsDashboardBuilder(api, storage)
|
||||
.Build(null)
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение списка радиостанций
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<List<YStation>>> GetStationsAsync(AuthStorage storage)
|
||||
{
|
||||
return new YGetStationsBuilder(api, storage)
|
||||
.Build(null)
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение информации о радиостанции
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="type">Тип</param>
|
||||
/// <param name="tag">Тэг</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<List<YStation>>> GetStationAsync(AuthStorage storage, string type, string tag)
|
||||
{
|
||||
return new YGetStationBuilder(api, storage)
|
||||
.Build((type, tag))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение информации о радиостанции
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="id">Идентификатор станции</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<List<YStation>>> GetStationAsync(AuthStorage storage, YStationId id)
|
||||
{
|
||||
return GetStationAsync(storage, id.Type, id.Tag);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение последовательности треков радиостанции
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="station">Радиостанция</param>
|
||||
/// <param name="prevTrackId">Идентификатор предыдущего трека</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YStationSequence>> GetStationTracksAsync(AuthStorage storage, YStation station, string prevTrackId = "")
|
||||
{
|
||||
return new YGetStationTracksBuilder(api, storage)
|
||||
.Build((station.Station, prevTrackId))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Установка настроек подбора треков
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="station">Радиостанция</param>
|
||||
/// <param name="settings">Настройки</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<string>> SetStationSettings2Async(AuthStorage storage, YStation station, YStationSettings2 settings)
|
||||
{
|
||||
return new YSetSettings2Builder(api, storage)
|
||||
.Build((station.Station, settings))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Отправка обратной связи на действия при прослушивании радио
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="station">Радиостанция</param>
|
||||
/// <param name="type">Тип обратной связи</param>
|
||||
/// <param name="track">Трек</param>
|
||||
/// <param name="batchId">Уникальный идентификатор партии треков. Возвращается при получении треков</param>
|
||||
/// <param name="totalPlayedSeconds">Сколько было проиграно секунд трека перед действием</param>
|
||||
/// <returns></returns>
|
||||
public Task<string> SendStationFeedBackAsync(AuthStorage storage, YStation station, YStationFeedbackType type, YTrack track = null, string batchId = "", double totalPlayedSeconds = 0)
|
||||
{
|
||||
return new YSetStationFeedbackBuilder(api, storage)
|
||||
.Build((type, station, track, batchId, totalPlayedSeconds))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
141
YandexMusic.API/API/YSearchAPIAsync.cs
Normal file
141
YandexMusic.API/API/YSearchAPIAsync.cs
Normal file
@@ -0,0 +1,141 @@
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Search;
|
||||
using YandexMusic.API.Requests.Search;
|
||||
|
||||
namespace YandexMusic.API
|
||||
{
|
||||
/// <summary>
|
||||
/// API для поиска
|
||||
/// </summary>
|
||||
public partial class YSearchAPI : YCommonAPI
|
||||
{
|
||||
|
||||
|
||||
public YSearchAPI(YandexMusicApi yandex) : base(yandex)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Поиск по трекам
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="trackName">Имя трека</param>
|
||||
/// <param name="pageNumber">Номер страницы</param>
|
||||
/// <param name="pageSize">Размер страницы</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YSearch>> TrackAsync(AuthStorage storage, string trackName, int pageNumber = 0, int pageSize = 20)
|
||||
{
|
||||
return SearchAsync(storage, trackName, YSearchType.Track, pageNumber, pageSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Поиск по альбомам
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="albumName">Имя альбома</param>
|
||||
/// <param name="pageNumber">Номер страницы</param>
|
||||
/// <param name="pageSize">Размер страницы</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YSearch>> AlbumsAsync(AuthStorage storage, string albumName, int pageNumber = 0, int pageSize = 20)
|
||||
{
|
||||
return SearchAsync(storage, albumName, YSearchType.Album, pageNumber, pageSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Поиск по артисту
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="artistName">Имя артиста</param>
|
||||
/// <param name="pageNumber">Номер страницы</param>
|
||||
/// <param name="pageSize">Размер страницы</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YSearch>> ArtistAsync(AuthStorage storage, string artistName, int pageNumber = 0, int pageSize = 20)
|
||||
{
|
||||
return SearchAsync(storage, artistName, YSearchType.Artist, pageNumber, pageSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Поиск по плейлистам
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="playlistName">Имя плейлиста</param>
|
||||
/// <param name="pageNumber">Номер страницы</param>
|
||||
/// <param name="pageSize">Размер страницы</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YSearch>> PlaylistAsync(AuthStorage storage, string playlistName, int pageNumber = 0, int pageSize = 20)
|
||||
{
|
||||
return SearchAsync(storage, playlistName, YSearchType.Playlist, pageNumber, pageSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Поиск по плейлистам
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="podcastName">Имя подкаста</param>
|
||||
/// <param name="pageNumber">Номер страницы</param>
|
||||
/// <param name="pageSize">Размер страницы</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YSearch>> PodcastEpisodeAsync(AuthStorage storage, string podcastName, int pageNumber = 0, int pageSize = 20)
|
||||
{
|
||||
return SearchAsync(storage, podcastName, YSearchType.PodcastEpisode, pageNumber, pageSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Поиск по видео
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="videoName">Имя видео</param>
|
||||
/// <param name="pageNumber">Номер страницы</param>
|
||||
/// <param name="pageSize">Размер страницы</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YSearch>> VideosAsync(AuthStorage storage, string videoName, int pageNumber = 0, int pageSize = 20)
|
||||
{
|
||||
return SearchAsync(storage, videoName, YSearchType.Video, pageNumber, pageSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Поиск по пользователям
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="userName">Имя пользователя</param>
|
||||
/// <param name="pageNumber">Номер страницы</param>
|
||||
/// <param name="pageSize">Размер страницы</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YSearch>> UsersAsync(AuthStorage storage, string userName, int pageNumber = 0, int pageSize = 20)
|
||||
{
|
||||
return SearchAsync(storage, userName, YSearchType.User, pageNumber, pageSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Поиск
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="searchText">Поисковый запрос</param>
|
||||
/// <param name="searchType">Тип поиска</param>
|
||||
/// <param name="page">Страница</param>
|
||||
/// <param name="pageSize">Размер страницы</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YSearch>> SearchAsync(AuthStorage storage, string searchText, YSearchType searchType, int page = 0, int pageSize = 20)
|
||||
{
|
||||
return new YSearchBuilder(api, storage)
|
||||
.Build((searchText, searchType, page, pageSize))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Подсказка
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="searchText">Поисковый запрос</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YSearchSuggest>> SuggestAsync(AuthStorage storage, string searchText)
|
||||
{
|
||||
return new YSearchSuggestBuilder(api, storage)
|
||||
.Build(searchText)
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
308
YandexMusic.API/API/YTrackAPIAsync.cs
Normal file
308
YandexMusic.API/API/YTrackAPIAsync.cs
Normal file
@@ -0,0 +1,308 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Track;
|
||||
using YandexMusic.API.Requests.Track;
|
||||
|
||||
namespace YandexMusic.API
|
||||
{
|
||||
/// <summary>
|
||||
/// API для взаимодействия с треками
|
||||
/// </summary>
|
||||
public partial class YTrackAPI : YCommonAPI
|
||||
{
|
||||
#region Вспомогательные функции
|
||||
|
||||
private string BuildLinkForDownload(YTrackDownloadInfo mainDownloadResponse, YStorageDownloadFile storageDownload)
|
||||
{
|
||||
string path = storageDownload.Path;
|
||||
string host = storageDownload.Host;
|
||||
string ts = storageDownload.Ts;
|
||||
string s = storageDownload.S;
|
||||
string codec = mainDownloadResponse.Codec;
|
||||
|
||||
string secret = $"XGRlBW9FXlekgbPrRHuSiA{path.Substring(1, path.Length - 1)}{s}";
|
||||
MD5 md5 = MD5.Create();
|
||||
byte[] md5Hash = md5.ComputeHash(Encoding.UTF8.GetBytes(secret));
|
||||
HMACSHA1 hmacsha1 = new();
|
||||
byte[] hmasha1Hash = hmacsha1.ComputeHash(md5Hash);
|
||||
string sign = BitConverter.ToString(hmasha1Hash).Replace("-", "").ToLower();
|
||||
|
||||
string link = $"https://{host}/get-{codec}/{sign}/{ts}{path}";
|
||||
|
||||
return link;
|
||||
}
|
||||
|
||||
#endregion Вспомогательные функции
|
||||
|
||||
|
||||
|
||||
public YTrackAPI(YandexMusicApi yandex) : base(yandex)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение треков
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="trackId">Идентификатор трека</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<List<YTrack>>> GetAsync(AuthStorage storage, string trackId)
|
||||
{
|
||||
return new YGetTracksBuilder(api, storage)
|
||||
.Build(new[] { trackId })
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение треков
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="trackIds">Идентификаторы треков</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<List<YTrack>>> GetAsync(AuthStorage storage, IEnumerable<string> trackIds)
|
||||
{
|
||||
return new YGetTracksBuilder(api, storage)
|
||||
.Build(trackIds)
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение метаданных для загрузки
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="trackKey">Ключ трека в формате {идентифактор трека:идентификатор альбома}</param>
|
||||
/// <param name="direct">Должен ли ответ содержать прямую ссылку на загрузку</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<List<YTrackDownloadInfo>>> GetMetadataForDownloadAsync(AuthStorage storage, string trackKey, bool direct = false)
|
||||
{
|
||||
return new YTrackDownloadInfoBuilder(api, storage)
|
||||
.Build((trackKey, direct))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение метаданных для загрузки
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="track">Трек</param>
|
||||
/// <param name="direct">Должен ли ответ содержать прямую ссылку на загрузку</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<List<YTrackDownloadInfo>>> GetMetadataForDownloadAsync(AuthStorage storage, YTrack track, bool direct = false)
|
||||
{
|
||||
return GetMetadataForDownloadAsync(storage, track.GetKey().ToString(), direct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение информации для формирования ссылки для загрузки
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="metadataInfo">Метаданные для загрузки</param>
|
||||
/// <returns></returns>
|
||||
public Task<YStorageDownloadFile> GetDownloadFileInfoAsync(AuthStorage storage, YTrackDownloadInfo metadataInfo)
|
||||
{
|
||||
return new YStorageDownloadFileBuilder(api, storage)
|
||||
.Build(metadataInfo.DownloadInfoUrl)
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение ссылки для загрузки
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="trackKey">Ключ трека в формате {идентификатор трека:идентификатор альбома}</param>
|
||||
/// <returns></returns>
|
||||
public async Task<string> GetFileLinkAsync(AuthStorage storage, string trackKey)
|
||||
{
|
||||
YResponse<List<YTrackDownloadInfo>> meta = await GetMetadataForDownloadAsync(storage, trackKey);
|
||||
YTrackDownloadInfo info = meta.Result
|
||||
.OrderByDescending(i => i.BitrateInKbps)
|
||||
.First(m => m.Codec == "mp3");
|
||||
YStorageDownloadFile storageDownload = await GetDownloadFileInfoAsync(storage, info);
|
||||
return BuildLinkForDownload(info, storageDownload);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение ссылки для загрузки
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="track">Трек</param>
|
||||
/// <returns></returns>
|
||||
public Task<string> GetFileLinkAsync(AuthStorage storage, YTrack track)
|
||||
{
|
||||
return GetFileLinkAsync(storage, track.GetKey().ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Отправка текущего состояния прослушиваемого трека
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="track">Трек</param>
|
||||
/// <param name="from">Наименования клиента, с которого происходит прослушивание</param>
|
||||
/// <param name="fromCache">Проигрывается ли трек с кеша</param>
|
||||
/// <param name="playId">Уникальный идентификатор проигрывания</param>
|
||||
/// <param name="playlistId">Уникальный идентификатор плейлиста, если таковой прослушивается</param>
|
||||
/// <param name="totalPlayedSeconds">Сколько было всего воспроизведено трека в секундах</param>
|
||||
/// <param name="endPositionSeconds">Окончательное значение воспроизведенных секунд</param>
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Task<string> SendPlayTrackInfoAsync(AuthStorage storage, YTrack track, string from, bool fromCache = false, string playId = "", string playlistId = "", double totalPlayedSeconds = 0, double endPositionSeconds = 0)
|
||||
{
|
||||
return new YSendTrackInfoBuilder(api, storage)
|
||||
.Build((track, from, fromCache, playId, playlistId, totalPlayedSeconds, endPositionSeconds))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
#region GetSupplement
|
||||
|
||||
/// <summary>
|
||||
/// Получение дополнительной информации для трека
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="trackId">Идентификатор трека</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YTrackSupplement>> GetSupplementAsync(AuthStorage storage, string trackId)
|
||||
{
|
||||
return new YGetTrackSupplementBuilder(api, storage)
|
||||
.Build(trackId)
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение дополнительной информации для трека
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="track">Трек</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YTrackSupplement>> GetSupplementAsync(AuthStorage storage, YTrack track)
|
||||
{
|
||||
return new YGetTrackSupplementBuilder(api, storage)
|
||||
.Build(track.GetKey().ToString())
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
#endregion GetSupplement
|
||||
|
||||
#region GetSimilar
|
||||
|
||||
/// <summary>
|
||||
/// Получение похожих треков
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="trackId">Идентификатор трека</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YTrackSimilar>> GetSimilarAsync(AuthStorage storage, string trackId)
|
||||
{
|
||||
return new YGetTrackSimilarBuilder(api, storage)
|
||||
.Build(trackId)
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение похожих треков
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="track">Трек</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YTrackSimilar>> GetSimilarAsync(AuthStorage storage, YTrack track)
|
||||
{
|
||||
return new YGetTrackSimilarBuilder(api, storage)
|
||||
.Build(track.GetKey().ToString())
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
#endregion GetSimilar
|
||||
|
||||
#region Получение данных трека
|
||||
|
||||
#region В файл
|
||||
|
||||
/// <summary>
|
||||
/// Выгрузка в файл
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="trackKey">Ключ трека в формате {идентификатор трека:идентификатор альбома}</param>
|
||||
/// <param name="filePath">Путь для файла</param>
|
||||
public async Task ExtractToFileAsync(AuthStorage storage, string trackKey, string filePath)
|
||||
{
|
||||
string url = await GetFileLinkAsync(storage, trackKey);
|
||||
await new DataDownloader(storage).ToFile(url, filePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Выгрузка в файл
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="track">Трек</param>
|
||||
/// <param name="filePath">Путь для файла</param>
|
||||
public Task ExtractToFileAsync(AuthStorage storage, YTrack track, string filePath)
|
||||
{
|
||||
return ExtractToFileAsync(storage, track.GetKey().ToString(), filePath);
|
||||
}
|
||||
|
||||
#endregion В файл
|
||||
|
||||
#region В массив байт
|
||||
|
||||
/// <summary>
|
||||
/// Получение двоичного массива данных
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="trackKey">Ключ трека в формате {идентификатор трека:идентификатор альбома}</param>
|
||||
/// <returns></returns>
|
||||
public async Task<byte[]> ExtractDataAsync(AuthStorage storage, string trackKey)
|
||||
{
|
||||
string url = await GetFileLinkAsync(storage, trackKey);
|
||||
return await new DataDownloader(storage).AsBytes(url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение двоичного массива данных
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="track">Трек</param>
|
||||
/// <returns></returns>
|
||||
public Task<byte[]> ExtractDataAsync(AuthStorage storage, YTrack track)
|
||||
{
|
||||
return ExtractDataAsync(storage, track.GetKey().ToString());
|
||||
}
|
||||
|
||||
#endregion В массив байт
|
||||
|
||||
#region В поток
|
||||
|
||||
/// <summary>
|
||||
/// Получение потока данных
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="trackKey">Ключ трека в формате {идентификатор трека:идентификатор альбома}</param>
|
||||
/// <param name="httpCompletionOption">Параметры передачи управления при http запросе</param>
|
||||
/// <returns></returns>
|
||||
public async Task<Stream> ExtractStreamAsync(AuthStorage storage, string trackKey,
|
||||
HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead)
|
||||
{
|
||||
string url = await GetFileLinkAsync(storage, trackKey);
|
||||
return await new DataDownloader(storage).AsStream(url, httpCompletionOption);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение потока данных
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="track">Трек</param>
|
||||
/// <param name="httpCompletionOption">Параметры передачи управления при http запросе</param>
|
||||
/// <returns></returns>
|
||||
public Task<Stream> ExtractStreamAsync(AuthStorage storage, YTrack track,
|
||||
HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead)
|
||||
{
|
||||
return ExtractStreamAsync(storage, track.GetKey().ToString(), httpCompletionOption);
|
||||
}
|
||||
|
||||
#endregion В поток
|
||||
|
||||
#endregion Получение данных трека
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
72
YandexMusic.API/API/YUgcAPIAsync.cs
Normal file
72
YandexMusic.API/API/YUgcAPIAsync.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Playlist;
|
||||
using YandexMusic.API.Models.Ugc;
|
||||
using YandexMusic.API.Requests.Ugc;
|
||||
|
||||
namespace YandexMusic.API
|
||||
{
|
||||
public partial class YUgcAPI : YCommonAPI
|
||||
{
|
||||
public YUgcAPI(YandexMusicApi yandex) : base(yandex)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение ссылки на загрузчик трека
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="playlist">Плейлист, куда будет загружен трек</param>
|
||||
/// <param name="fileName">Название файла для загрузки</param>
|
||||
public Task<YUgcUpload> GetUgcUploadLinkAsync(AuthStorage storage, YPlaylist playlist, string fileName)
|
||||
{
|
||||
return new YUgcGetUploadLinkBuilder(api, storage)
|
||||
.Build((playlist, fileName))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Загрузка трека из файла
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="uploadLink">Ссылка на балансировщик для загрузки, можно получить из GetUgcUploadLinkAsync</param>
|
||||
/// <param name="filePath">Загружаемый файл</param>
|
||||
public Task<YResponse<string>> UploadUgcTrackAsync(AuthStorage storage, string uploadLink, string filePath)
|
||||
{
|
||||
if (!File.Exists(filePath))
|
||||
throw new FileNotFoundException("Файл для загрузки не существует.", filePath);
|
||||
|
||||
return UploadUgcTrackAsync(storage, uploadLink, File.Open(filePath, FileMode.Open));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Загрузка трека из потока
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="uploadLink">Ссылка на балансировщик для загрузки, можно получить из GetUgcUploadLinkAsync</param>
|
||||
/// <param name="stream">Поток с данными для загрузки</param>
|
||||
public Task<YResponse<string>> UploadUgcTrackAsync(AuthStorage storage, string uploadLink, Stream stream)
|
||||
{
|
||||
if (stream == null)
|
||||
throw new NullReferenceException("Пустая ссылка на поток загрузки.");
|
||||
|
||||
using MemoryStream ms = new();
|
||||
stream.CopyTo(ms);
|
||||
|
||||
return UploadUgcTrackAsync(storage, uploadLink, ms.ToArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Загрузка трека из массива
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="uploadLink">Ссылка на балансировщик для загрузки, можно получить из GetUgcUploadLinkAsync</param>
|
||||
/// <param name="file">Загружаемый трек в виде массив байтов</param>
|
||||
public Task<YResponse<string>> UploadUgcTrackAsync(AuthStorage storage, string uploadLink, byte[] file)
|
||||
{
|
||||
return new YUgcUploadBuilder(api, storage)
|
||||
.Build((uploadLink, file))
|
||||
.GetResponseAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
303
YandexMusic.API/API/YUserAPIAsync.cs
Normal file
303
YandexMusic.API/API/YUserAPIAsync.cs
Normal file
@@ -0,0 +1,303 @@
|
||||
using System.Security.Authentication;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Account;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Requests.Account;
|
||||
|
||||
namespace YandexMusic.API
|
||||
{
|
||||
/// <summary>
|
||||
/// API для пользователя
|
||||
/// </summary>
|
||||
public partial class YUserAPI : YCommonAPI
|
||||
{
|
||||
#region Вспомогательные функции
|
||||
|
||||
private async Task<bool> GetCsrfTokenAsync(AuthStorage storage)
|
||||
{
|
||||
using HttpResponseMessage authMethodsResponse = await new YGetAuthMethodsBuilder(api, storage)
|
||||
.Build(null)
|
||||
.GetResponseAsync();
|
||||
|
||||
if (!authMethodsResponse.IsSuccessStatusCode)
|
||||
throw new HttpRequestException("Невозможно получить CFRF-токен.");
|
||||
|
||||
string responseString = await authMethodsResponse.Content
|
||||
.ReadAsStringAsync();
|
||||
Match match = Regex.Match(responseString, "\"csrf_token\" value=\"([^\"]+)\"");
|
||||
|
||||
if (!match.Success || match.Groups.Count < 2)
|
||||
return false;
|
||||
|
||||
storage.AuthToken = new YAuthToken
|
||||
{
|
||||
CsfrToken = match.Groups[1].Value
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task<bool> LoginByCookiesAsync(AuthStorage storage)
|
||||
{
|
||||
if (storage.AuthToken == null)
|
||||
throw new AuthenticationException("Невозможно инициализировать сессию входа.");
|
||||
|
||||
YAccessToken accessToken = await new YGetAuthCookiesBuilder(api, storage)
|
||||
.Build(null)
|
||||
.GetResponseAsync();
|
||||
|
||||
storage.IsAuthorized = !string.IsNullOrEmpty(accessToken.AccessToken);
|
||||
|
||||
storage.AccessToken = accessToken;
|
||||
storage.Token = accessToken.AccessToken;
|
||||
|
||||
YShortAccountInfo validateTokenResponse = await new YGetShortAccountInifoBuilder(api, storage)
|
||||
.Build(null)
|
||||
.GetResponseAsync();
|
||||
|
||||
if (validateTokenResponse.Status != YAuthStatus.Ok)
|
||||
throw new Exception("Вход в аккаунт не выполнен.");
|
||||
|
||||
storage.IsAuthorized = !string.IsNullOrWhiteSpace(validateTokenResponse.Uid);
|
||||
|
||||
return storage.IsAuthorized;
|
||||
}
|
||||
|
||||
#endregion Вспомогательные функции
|
||||
|
||||
|
||||
|
||||
public YUserAPI(YandexMusicApi yandex) : base(yandex)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Авторизация
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="token">Токен авторизации</param>
|
||||
/// <returns></returns>
|
||||
public async Task AuthorizeAsync(AuthStorage storage, string token)
|
||||
{
|
||||
if (string.IsNullOrEmpty(token))
|
||||
throw new Exception("Задан пустой токен авторизации.");
|
||||
|
||||
storage.Token = token;
|
||||
|
||||
// Пытаемся получить информацию о пользователе
|
||||
YResponse<YAccountResult> authInfo = await GetUserAuthAsync(storage);
|
||||
|
||||
// Если не авторизован, то авторизуем
|
||||
if (string.IsNullOrEmpty(authInfo.Result.Account.Uid))
|
||||
throw new Exception("Пользователь незалогинен.");
|
||||
|
||||
// Флаг авторизации
|
||||
storage.IsAuthorized = true;
|
||||
storage.User = authInfo.Result.Account;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение информации об авторизации
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <returns></returns>
|
||||
public Task<YResponse<YAccountResult>> GetUserAuthAsync(AuthStorage storage)
|
||||
{
|
||||
return new YGetAuthInfoBuilder(api, storage)
|
||||
.Build(null)
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Создание сеанса и получение доступных методов авторизации
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="userName">Имя пользователя</param>
|
||||
/// <returns></returns>
|
||||
public async Task<YAuthTypes> CreateAuthSessionAsync(AuthStorage storage, string userName)
|
||||
{
|
||||
if (!await GetCsrfTokenAsync(storage))
|
||||
throw new Exception("Невозможно инициализировать сессию входа.");
|
||||
|
||||
YAuthTypes types = await new YGetAuthLoginUserBuilder(api, storage)
|
||||
.Build((storage.AuthToken.CsfrToken, userName))
|
||||
.GetResponseAsync();
|
||||
|
||||
storage.AuthToken.TrackId = types.TrackId;
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение ссылки на QR-код
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <returns></returns>
|
||||
public async Task<string> GetAuthQRLinkAsync(AuthStorage storage)
|
||||
{
|
||||
if (!await GetCsrfTokenAsync(storage))
|
||||
throw new Exception("Невозможно инициализировать сессию входа.");
|
||||
|
||||
YAuthQR result = await new YGetAuthQRBuilder(api, storage)
|
||||
.Build(null)
|
||||
.GetResponseAsync();
|
||||
|
||||
if (result.Status != YAuthStatus.Ok)
|
||||
return string.Empty;
|
||||
|
||||
storage.AuthToken = new YAuthToken
|
||||
{
|
||||
TrackId = result.TrackId,
|
||||
CsfrToken = result.CsrfToken
|
||||
};
|
||||
|
||||
return $"https://passport.yandex.ru/auth/magic/code/?track_id={result.TrackId}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Авторизация по QR-коду
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <returns></returns>
|
||||
public async Task<YAuthQRStatus> AuthorizeByQRAsync(AuthStorage storage)
|
||||
{
|
||||
if (storage.AuthToken == null)
|
||||
throw new Exception("Не выполнен запрос на авторизацию по QR.");
|
||||
|
||||
try
|
||||
{
|
||||
YAuthQRStatus qrStatus = await new YGetAuthLoginQRBuilder(api, storage)
|
||||
.Build(null)
|
||||
.GetResponseAsync();
|
||||
if (qrStatus.Status != YAuthStatus.Ok)
|
||||
return qrStatus;
|
||||
|
||||
bool ok = await LoginByCookiesAsync(storage);
|
||||
if (!ok)
|
||||
throw new AuthenticationException("Ошибка авторизации по QR.");
|
||||
|
||||
return qrStatus;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new AuthenticationException("Ошибка авторизации по QR.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение <see cref="YAuthCaptcha"/>
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <returns></returns>
|
||||
public Task<YAuthCaptcha> GetCaptchaAsync(AuthStorage storage)
|
||||
{
|
||||
if (storage.AuthToken == null || string.IsNullOrWhiteSpace(storage.AuthToken.CsfrToken))
|
||||
throw new AuthenticationException($"Не найдена сессия входа. Выполните {nameof(CreateAuthSessionAsync)} перед использованием.");
|
||||
|
||||
return new YGetAuthCaptchaBuilder(api, storage)
|
||||
.Build(null)
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Авторизация по captcha
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="captchaValue">Значение captcha</param>
|
||||
/// <returns></returns>
|
||||
public Task<YAuthBase> AuthorizeByCaptchaAsync(AuthStorage storage, string captchaValue)
|
||||
{
|
||||
if (storage.AuthToken == null || string.IsNullOrWhiteSpace(storage.AuthToken.CsfrToken))
|
||||
throw new AuthenticationException($"Не найдена сессия входа. Выполните {nameof(CreateAuthSessionAsync)} перед использованием.");
|
||||
|
||||
return new YGetAuthLoginCaptchaBuilder(api, storage)
|
||||
.Build(captchaValue)
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение письма авторизации на почту пользователя
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <returns></returns>
|
||||
public Task<YAuthLetter> GetAuthLetterAsync(AuthStorage storage)
|
||||
{
|
||||
return new YGetAuthLetterBuilder(api, storage)
|
||||
.Build(null)
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Авторизация после подтверждения входа через письмо
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> AuthorizeByLetterAsync(AuthStorage storage)
|
||||
{
|
||||
YAuthLetterStatus status = await new YGetAuthLoginLetterBuilder(api, storage)
|
||||
.Build(null)
|
||||
.GetResponseAsync();
|
||||
|
||||
if (status.Status == YAuthStatus.Ok && !status.MagicLinkConfirmed)
|
||||
throw new Exception("Не подтвержден вход посредством e-mail.");
|
||||
|
||||
return await LoginByCookiesAsync(storage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Авторизация с помощью пароля из приложения Яндекс
|
||||
/// </summary>
|
||||
/// <param name="storage">Хранилище</param>
|
||||
/// <param name="password">Пароль</param>
|
||||
/// <returns></returns>
|
||||
public async Task<YAuthBase> AuthorizeByAppPasswordAsync(AuthStorage storage, string password)
|
||||
{
|
||||
if (storage.AuthToken == null || string.IsNullOrWhiteSpace(storage.AuthToken.CsfrToken))
|
||||
throw new AuthenticationException($"Не найдена сессия входа. Выполните {nameof(CreateAuthSessionAsync)} перед использованием.");
|
||||
|
||||
YAuthBase response = await new YGetAuthAppPasswordBuilder(api, storage)
|
||||
.Build(password)
|
||||
.GetResponseAsync();
|
||||
|
||||
if (response.Status == YAuthStatus.Ok)
|
||||
{
|
||||
bool ok = await LoginByCookiesAsync(storage);
|
||||
if (!ok)
|
||||
throw new AuthenticationException("Ошибка авторизации.");
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение <see cref="YAccessToken"/> после авторизации с помощью QR, e-mail, пароля из приложения
|
||||
/// </summary>
|
||||
public async Task<YAccessToken> GetAccessTokenAsync(AuthStorage storage)
|
||||
{
|
||||
if (storage.AuthToken == null)
|
||||
throw new Exception("Не найдена сессия входа.");
|
||||
|
||||
YAccessToken accessToken = await new YGetMusicTokenBuilder(api, storage)
|
||||
.Build(null)
|
||||
.GetResponseAsync();
|
||||
|
||||
storage.Token = accessToken.AccessToken;
|
||||
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Получение информации о пользователе через логин Яндекса
|
||||
/// </summary>
|
||||
public Task<YLoginInfo> GetLoginInfoAsync(AuthStorage storage)
|
||||
{
|
||||
return new YGetLoginInfoBuilder(api, storage)
|
||||
.Build(null)
|
||||
.GetResponseAsync();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user