diff --git a/YandexMusic.API/API/YAlbumAPI.cs b/YandexMusic.API/API/YAlbumAPI.cs
index 8c52247..aa59ec6 100644
--- a/YandexMusic.API/API/YAlbumAPI.cs
+++ b/YandexMusic.API/API/YAlbumAPI.cs
@@ -1,6 +1,4 @@
-using YandexMusic.API.Common;
using YandexMusic.API.Models.Album;
-using YandexMusic.API.Models.Common;
using YandexMusic.API.Requests.Album;
namespace YandexMusic.API;
@@ -8,21 +6,13 @@ namespace YandexMusic.API;
/// API для работы с альбомами.
public class YAlbumAPI : YCommonAPI
{
- /// Инициализирует новый экземпляр API альбомов.
- /// Экземпляр основного API.
- public YAlbumAPI(YandexMusicApi yandex) : base(yandex) { }
+ public YAlbumAPI(YandexMusicApi api) : base(api) { }
/// Получает альбом по идентификатору.
- /// Хранилище данных авторизации.
- /// Идентификатор альбома.
- /// Ответ API с моделью альбома.
- public Task> GetAsync(AuthStorage storage, string albumId)
- => new YGetAlbumBuilder(api, storage).Build(albumId).GetResponseAsync();
+ public Task GetAsync(string albumId)
+ => new YGetAlbumBuilder(Api).ExecuteAsync(albumId);
/// Получает несколько альбомов по списку идентификаторов.
- /// Хранилище данных авторизации.
- /// Список идентификаторов альбомов.
- /// Ответ API со списком альбомов.
- public Task>> GetAsync(AuthStorage storage, IEnumerable albumIds)
- => new YGetAlbumsBuilder(api, storage).Build(albumIds).GetResponseAsync();
+ public Task?> GetAsync(IEnumerable albumIds)
+ => new YGetAlbumsBuilder(Api).ExecuteAsync(albumIds);
}
\ No newline at end of file
diff --git a/YandexMusic.API/API/YArtistAPI.cs b/YandexMusic.API/API/YArtistAPI.cs
index f132417..8a1a2ea 100644
--- a/YandexMusic.API/API/YArtistAPI.cs
+++ b/YandexMusic.API/API/YArtistAPI.cs
@@ -1,71 +1,27 @@
-using YandexMusic.API.Common;
using YandexMusic.API.Models.Artist;
-using YandexMusic.API.Models.Common;
using YandexMusic.API.Requests.Artist;
namespace YandexMusic.API;
-///
-/// API для взаимодействия с исполнителями
-///
+/// API для работы с исполнителями.
public class YArtistAPI : YCommonAPI
{
- public YArtistAPI(YandexMusicApi yandex) : base(yandex)
+ public YArtistAPI(YandexMusicApi api) : base(api) { }
+
+ public Task GetAsync(string artistId)
+ => new YGetArtistBuilder(Api).ExecuteAsync(artistId);
+
+ public Task?> GetAsync(IEnumerable artistIds)
+ => new YGetArtistsBuilder(Api).ExecuteAsync(artistIds);
+
+ public Task GetTracksAsync(string artistId, int page = 0, int pageSize = 20)
+ => new YGetArtistTrackBuilder(Api).ExecuteAsync((artistId, page, pageSize));
+
+ public async Task GetAllTracksAsync(string artistId)
{
+ var info = await GetAsync(artistId);
+ if (info?.Artist?.Counts?.Tracks == null)
+ return null;
+ return await GetTracksAsync(artistId, pageSize: info.Artist.Counts.Tracks);
}
-
- ///
- /// Получение исполнителя
- ///
- /// Хранилище
- /// Идентификатор
- public Task> GetAsync(AuthStorage storage, string artistId)
- {
- return new YGetArtistBuilder(api, storage)
- .Build(artistId)
- .GetResponseAsync();
- }
-
- ///
- /// Получение исполнителей
- ///
- /// Хранилище
- /// Идентификаторы
- public Task>> GetAsync(AuthStorage storage, IEnumerable artistIds)
- {
- return new YGetArtistsBuilder(api, storage)
- .Build(artistIds)
- .GetResponseAsync();
- }
-
- ///
- /// Получение треков исполнителя с пагинацией
- ///
- /// Треки поставляются по штук на страницу,
- /// для получения всех треков необходимо использовать метод
- ///
- ///
- /// Хранилище
- /// Идентификатор исполнителя
- /// Страница ответов
- /// Количество треков на странице ответов
- public Task> GetTracksAsync(AuthStorage storage, string artistId, int page = 0, int pageSize = 20)
- {
- return new YGetArtistTrackBuilder(api, storage)
- .Build((artistId, page, pageSize))
- .GetResponseAsync();
- }
-
- ///
- /// Получение всех треков исполнителя
- ///
- /// Хранилище
- /// Идентификатор исполнителя
- public async Task> GetAllTracksAsync(AuthStorage storage, string artistId)
- {
- YResponse response = await GetAsync(storage, artistId);
- return await GetTracksAsync(storage, artistId, pageSize: response.Result.Artist.Counts.Tracks);
- }
-
-
}
\ No newline at end of file
diff --git a/YandexMusic.API/API/YCommonAPI.cs b/YandexMusic.API/API/YCommonAPI.cs
index b0f63dc..dab25a4 100644
--- a/YandexMusic.API/API/YCommonAPI.cs
+++ b/YandexMusic.API/API/YCommonAPI.cs
@@ -1,12 +1,10 @@
namespace YandexMusic.API;
-/// Родительский класс для всех веток API.
+/// Базовый класс для всех веток API.
public abstract class YCommonAPI
{
/// Основной экземпляр API.
- protected readonly YandexMusicApi api;
+ protected YandexMusicApi Api { get; }
- /// Инициализирует новый экземпляр.
- /// Экземпляр основного API.
- protected YCommonAPI(YandexMusicApi yandex) => api = yandex;
+ protected YCommonAPI(YandexMusicApi api) => Api = api;
}
\ No newline at end of file
diff --git a/YandexMusic.API/API/YLabelAPI.cs b/YandexMusic.API/API/YLabelAPI.cs
index 42b53c8..245e5a7 100644
--- a/YandexMusic.API/API/YLabelAPI.cs
+++ b/YandexMusic.API/API/YLabelAPI.cs
@@ -1,39 +1,19 @@
-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
+/// API для работы с лейблами.
+public class YLabelAPI : YCommonAPI
{
- public YLabelAPI(YandexMusicApi yandex) : base(yandex)
- {
- }
+ public YLabelAPI(YandexMusicApi api) : base(api) { }
- ///
- /// Постраничное получение альбомов лейбла
- ///
- /// Хранилище
- /// Лейбл
- /// Страница
- public Task> GetAlbumsByLabelAsync(AuthStorage storage, YLabel label, int page)
- {
- return new YGetLabelAlbumsBuilder(api, storage)
- .Build((label, page))
- .GetResponseAsync();
- }
+ /// Получает альбомы лейбла с пагинацией.
+ public Task GetAlbumsByLabelAsync(YLabel label, int page = 0)
+ => new YGetLabelAlbumsBuilder(Api).ExecuteAsync((label, page));
- ///
- /// Постраничное получение артистов лейбла
- ///
- /// Хранилище
- /// Лейбл
- /// Страница
- public Task> GetArtistsByLabelAsync(AuthStorage storage, YLabel label, int page)
- {
- return new YGetLabelArtistsBuilder(api, storage)
- .Build((label, page))
- .GetResponseAsync();
- }
+ /// Получает артистов лейбла с пагинацией.
+ public Task GetArtistsByLabelAsync(YLabel label, int page = 0)
+ => new YGetLabelArtistsBuilder(Api).ExecuteAsync((label, page));
}
\ No newline at end of file
diff --git a/YandexMusic.API/API/YLandingAPI.cs b/YandexMusic.API/API/YLandingAPI.cs
index b91cecc..847b912 100644
--- a/YandexMusic.API/API/YLandingAPI.cs
+++ b/YandexMusic.API/API/YLandingAPI.cs
@@ -1,43 +1,21 @@
-using YandexMusic.API.Common;
-using YandexMusic.API.Models.Common;
-using YandexMusic.API.Models.Feed;
+using YandexMusic.API.Models.Feed;
using YandexMusic.API.Models.Landing;
using YandexMusic.API.Requests.Feed;
using YandexMusic.API.Requests.Landing;
namespace YandexMusic.API;
-/// API для взаимодействия с главной страницей (лендингом).
+/// API для работы с главной страницей (лендингом).
public class YLandingAPI : YCommonAPI
{
- /// Инициализирует новый экземпляр API лендинга.
- /// Экземпляр основного API.
- public YLandingAPI(YandexMusicApi yandex) : base(yandex) { }
+ public YLandingAPI(YandexMusicApi api) : base(api) { }
- /// Получает персональные блоки лендинга.
- /// Хранилище авторизации.
- /// Типы запрашиваемых блоков.
- /// Ответ API с лендингом.
- /// Если массив blocks равен null.
- public Task> GetAsync(AuthStorage storage, params YLandingBlockType[] blocks)
- {
- if (blocks == null)
- throw new ArgumentNullException(nameof(blocks), "Массив блоков не может быть null");
+ public Task GetAsync(params YLandingBlockType[] blocks)
+ => new YGetLandingBuilder(Api).ExecuteAsync(blocks);
- return new YGetLandingBuilder(api, storage)
- .Build(blocks)
- .GetResponseAsync();
- }
+ public Task GetFeedAsync()
+ => new YGetFeedBuilder(Api).ExecuteAsync(null!);
- /// Получает ленту событий (фид).
- /// Хранилище авторизации.
- /// Ответ API с лентой.
- public Task> GetFeedAsync(AuthStorage storage)
- => new YGetFeedBuilder(api, storage).Build(null!).GetResponseAsync();
-
- /// Получает лендинг детского раздела.
- /// Хранилище авторизации.
- /// Ответ API с детским лендингом.
- public Task> GetChildrenLandingAsync(AuthStorage storage)
- => new YGetChildrenLandingBuilder(api, storage).Build(null!).GetResponseAsync();
+ public Task GetChildrenLandingAsync()
+ => new YGetChildrenLandingBuilder(Api).ExecuteAsync(null!);
}
\ No newline at end of file
diff --git a/YandexMusic.API/API/YLibraryAPI.cs b/YandexMusic.API/API/YLibraryAPI.cs
index df1b86c..95da341 100644
--- a/YandexMusic.API/API/YLibraryAPI.cs
+++ b/YandexMusic.API/API/YLibraryAPI.cs
@@ -1,4 +1,3 @@
-using YandexMusic.API.Common;
using YandexMusic.API.Models.Album;
using YandexMusic.API.Models.Artist;
using YandexMusic.API.Models.Common;
@@ -10,244 +9,82 @@ using YandexMusic.API.Requests.Library;
namespace YandexMusic.API;
-///
-/// API для взаимодействия с библиотекой
-///
-public partial class YLibraryAPI : YCommonAPI
+/// API для работы с библиотекой (лайки, дизлайки, недавно прослушанное).
+public class YLibraryAPI : YCommonAPI
{
- ///
- /// Получение секции библиотеки
- ///
- /// Тип объекта библиотеки
- /// Хранилище
- /// Секция
- /// Тип
- /// Список объектов из секции
- private Task> GetLibrarySection(AuthStorage storage, YLibrarySection section, YLibrarySectionType type = YLibrarySectionType.Likes)
- {
- return new YGetLibrarySectionBuilder(api, storage)
- .Build((section, type))
- .GetResponseAsync();
- }
-
-
-
- public YLibraryAPI(YandexMusicApi yandex) : base(yandex)
- {
- }
+ public YLibraryAPI(YandexMusicApi api) : base(api) { }
#region Лайки
- ///
- /// Получение лайкнутых треков
- ///
- /// Хранилище
- ///
- public Task> GetLikedTracksAsync(AuthStorage storage)
- {
- return GetLibrarySection(storage, YLibrarySection.Tracks);
- }
+ public Task GetLikedTracksAsync()
+ => new YGetLibrarySectionBuilder(Api).ExecuteAsync((YLibrarySection.Tracks, YLibrarySectionType.Likes));
- ///
- /// Получение лайкнутых альбомов
- ///
- /// Хранилище
- ///
- public Task>> GetLikedAlbumsAsync(AuthStorage storage)
- {
- return GetLibrarySection>(storage, YLibrarySection.Albums);
- }
+ public Task?> GetLikedAlbumsAsync()
+ => new YGetLibrarySectionBuilder>(Api).ExecuteAsync((YLibrarySection.Albums, YLibrarySectionType.Likes));
- ///
- /// Получение лайкнутых исполнителей
- ///
- /// Хранилище
- ///
- public Task>> GetLikedArtistsAsync(AuthStorage storage)
- {
- return GetLibrarySection>(storage, YLibrarySection.Artists);
- }
+ public Task?> GetLikedArtistsAsync()
+ => new YGetLibrarySectionBuilder>(Api).ExecuteAsync((YLibrarySection.Artists, YLibrarySectionType.Likes));
- ///
- /// Получение лайкнутых плейлистов
- ///
- /// Хранилище
- ///
- public Task>> GetLikedPlaylistsAsync(AuthStorage storage)
- {
- return GetLibrarySection>(storage, YLibrarySection.Playlists);
- }
+ public Task?> GetLikedPlaylistsAsync()
+ => new YGetLibrarySectionBuilder>(Api).ExecuteAsync((YLibrarySection.Playlists, YLibrarySectionType.Likes));
- #endregion Лайки
+ #endregion
#region Дизлайки
- ///
- /// Получение дизлайкнутых треков
- ///
- /// Хранилище
- ///
- public Task> GetDislikedTracksAsync(AuthStorage storage)
- {
- return GetLibrarySection(storage, YLibrarySection.Tracks, YLibrarySectionType.Dislikes);
- }
+ public Task GetDislikedTracksAsync()
+ => new YGetLibrarySectionBuilder(Api).ExecuteAsync((YLibrarySection.Tracks, YLibrarySectionType.Dislikes));
- ///
- /// Получение дизлайкнутых исполнителей
- ///
- /// Хранилище
- ///
- public Task>> GetDislikedArtistsAsync(AuthStorage storage)
- {
- return GetLibrarySection>(storage, YLibrarySection.Artists, YLibrarySectionType.Dislikes);
- }
+ public Task?> GetDislikedArtistsAsync()
+ => new YGetLibrarySectionBuilder>(Api).ExecuteAsync((YLibrarySection.Artists, YLibrarySectionType.Dislikes));
- #endregion Дизлайки
+ #endregion
- #region Добавление в списки лайков/дизлайков
+ #region Добавление/удаление
- ///
- /// Добавить трек в список лайкнутых
- ///
- /// Хранилище
- /// Трек
- ///
- public Task> AddTrackLikeAsync(AuthStorage storage, YTrack track)
- {
- return new YLibraryAddBuilder(api, storage)
- .Build((track.GetKey().ToString(), YLibrarySection.Tracks, YLibrarySectionType.Likes))
- .GetResponseAsync();
- }
+ public Task AddTrackLikeAsync(YTrack track)
+ => new YLibraryAddBuilder(Api).ExecuteAsync((track.Id, YLibrarySection.Tracks, YLibrarySectionType.Likes))
+ .ContinueWith(t => t.Result?.Revision);
- ///
- /// Удалить трек из списка лайкнутых
- ///
- /// Хранилище
- /// Трек
- ///
- public Task> RemoveTrackLikeAsync(AuthStorage storage, YTrack track)
- {
- return new YLibraryRemoveBuilder(api, storage)
- .Build((track.GetKey().ToString(), YLibrarySection.Tracks, YLibrarySectionType.Likes))
- .GetResponseAsync();
- }
+ public Task RemoveTrackLikeAsync(YTrack track)
+ => new YLibraryRemoveBuilder(Api).ExecuteAsync((track.Id, YLibrarySection.Tracks, YLibrarySectionType.Likes))
+ .ContinueWith(t => t.Result?.Revision);
- ///
- /// Добавить трек в список дизлайкнутых
- ///
- /// Хранилище
- /// Трек
- ///
- public Task> AddTrackDislikeAsync(AuthStorage storage, YTrack track)
- {
- return new YLibraryAddBuilder(api, storage)
- .Build((track.GetKey().ToString(), YLibrarySection.Tracks, YLibrarySectionType.Dislikes))
- .GetResponseAsync();
- }
+ public Task AddTrackDislikeAsync(YTrack track)
+ => new YLibraryAddBuilder(Api).ExecuteAsync((track.Id, YLibrarySection.Tracks, YLibrarySectionType.Dislikes))
+ .ContinueWith(t => t.Result?.Revision);
- ///
- /// Удалить трек из списка дизлайкнутых
- ///
- /// Хранилище
- /// Трек
- ///
- public Task> RemoveTrackDislikeAsync(AuthStorage storage, YTrack track)
- {
- return new YLibraryRemoveBuilder(api, storage)
- .Build((track.GetKey().ToString(), YLibrarySection.Tracks, YLibrarySectionType.Dislikes))
- .GetResponseAsync();
- }
+ public Task RemoveTrackDislikeAsync(YTrack track)
+ => new YLibraryRemoveBuilder(Api).ExecuteAsync((track.Id, YLibrarySection.Tracks, YLibrarySectionType.Dislikes))
+ .ContinueWith(t => t.Result?.Revision);
- ///
- /// Добавить альбом в список лайкнутых
- ///
- /// Хранилище
- /// Альбом
- ///
- public Task> AddAlbumLikeAsync(AuthStorage storage, YAlbum album)
- {
- return new YLibraryAddBuilder(api, storage)
- .Build((album.Id, YLibrarySection.Albums, YLibrarySectionType.Likes))
- .GetResponseAsync();
- }
+ public Task AddAlbumLikeAsync(YAlbum album)
+ => new YLibraryAddBuilder(Api).ExecuteAsync((album.Id, YLibrarySection.Albums, YLibrarySectionType.Likes));
- ///
- /// Удалить альбом из списка лайкнутых
- ///
- /// Хранилище
- /// Альбом
- ///
- public Task> RemoveAlbumLikeAsync(AuthStorage storage, YAlbum album)
- {
- return new YLibraryRemoveBuilder(api, storage)
- .Build((album.Id, YLibrarySection.Albums, YLibrarySectionType.Likes))
- .GetResponseAsync();
- }
+ public Task RemoveAlbumLikeAsync(YAlbum album)
+ => new YLibraryRemoveBuilder(Api).ExecuteAsync((album.Id, YLibrarySection.Albums, YLibrarySectionType.Likes));
- ///
- /// Добавить исполнителя в список лайкнутых
- ///
- /// Хранилище
- /// Исполнитель
- ///
- public Task> AddArtistLikeAsync(AuthStorage storage, YArtist artist)
- {
- return new YLibraryAddBuilder(api, storage)
- .Build((artist.Id, YLibrarySection.Artists, YLibrarySectionType.Likes))
- .GetResponseAsync();
- }
+ public Task AddArtistLikeAsync(YArtist artist)
+ => new YLibraryAddBuilder(Api).ExecuteAsync((artist.Id, YLibrarySection.Artists, YLibrarySectionType.Likes));
- ///
- /// Удалить исполнителя из списка лайкнутых
- ///
- /// Хранилище
- /// Исполнитель
- ///
- public Task> RemoveArtistLikeAsync(AuthStorage storage, YArtist artist)
- {
- return new YLibraryRemoveBuilder(api, storage)
- .Build((artist.Id, YLibrarySection.Artists, YLibrarySectionType.Likes))
- .GetResponseAsync();
- }
+ public Task RemoveArtistLikeAsync(YArtist artist)
+ => new YLibraryRemoveBuilder(Api).ExecuteAsync((artist.Id, YLibrarySection.Artists, YLibrarySectionType.Likes));
- ///
- /// Добавить плейлист в список лайкнутых
- ///
- /// Хранилище
- /// Плейлист
- ///
- public Task> AddPlaylistLikeAsync(AuthStorage storage, YPlaylist playlist)
- {
- return new YLibraryAddBuilder(api, storage)
- .Build((playlist.GetKey().ToString(), YLibrarySection.Playlists, YLibrarySectionType.Likes))
- .GetResponseAsync();
- }
+ public Task AddPlaylistLikeAsync(YPlaylist playlist)
+ => new YLibraryAddBuilder(Api).ExecuteAsync((playlist.GetKey().ToString(), YLibrarySection.Playlists, YLibrarySectionType.Likes));
- ///
- /// Удалить плейлист из списка лайкнутых
- ///
- /// Хранилище
- /// Плейлист
- ///
- public Task> RemovePlaylistLikeAsync(AuthStorage storage, YPlaylist playlist)
- {
- return new YLibraryRemoveBuilder(api, storage)
- .Build((playlist.GetKey().ToString(), YLibrarySection.Playlists, YLibrarySectionType.Likes))
- .GetResponseAsync();
- }
+ public Task RemovePlaylistLikeAsync(YPlaylist playlist)
+ => new YLibraryRemoveBuilder(Api).ExecuteAsync((playlist.GetKey().ToString(), YLibrarySection.Playlists, YLibrarySectionType.Likes));
- #endregion Добавление/удаление в списки лайков/дизлайков
+ #endregion
- #region Получение списка "Вы недавно слушали"
-
- public Task> GetRecentlyListenedAsync(AuthStorage storage, IEnumerable contextTypes, int trackCount, int contextCount)
- {
- return new YGetLibraryRecentlyListenedBuilder(api, storage)
- .Build((contextTypes, trackCount, contextCount))
- .GetResponseAsync();
- }
-
- #endregion Получение списка "Вы недавно слушали"
+ #region Недавно прослушанное
+ public Task GetRecentlyListenedAsync(
+ IEnumerable contextTypes,
+ int trackCount = 50,
+ int contextCount = 10)
+ => new YGetLibraryRecentlyListenedBuilder(Api).ExecuteAsync((contextTypes, trackCount, contextCount));
+ #endregion
}
\ No newline at end of file
diff --git a/YandexMusic.API/API/YPinsAPI.cs b/YandexMusic.API/API/YPinsAPI.cs
index bc1dc4f..1de69b8 100644
--- a/YandexMusic.API/API/YPinsAPI.cs
+++ b/YandexMusic.API/API/YPinsAPI.cs
@@ -1,20 +1,13 @@
-using YandexMusic.API.Common;
-using YandexMusic.API.Models.Common;
using YandexMusic.API.Models.Pins;
using YandexMusic.API.Requests.Pins;
namespace YandexMusic.API;
-/// API для взаимодействия с закреплёнными объектами (пинами).
+/// API для работы с закреплёнными объектами (пинами).
public class YPinsAPI : YCommonAPI
{
- /// Инициализирует новый экземпляр API пинов.
- /// Экземпляр основного API.
- public YPinsAPI(YandexMusicApi yandex) : base(yandex) { }
+ public YPinsAPI(YandexMusicApi api) : base(api) { }
- /// Получает список закреплённых объектов.
- /// Хранилище авторизации.
- /// Ответ API со списком пинов.
- public Task> GetAsync(AuthStorage storage)
- => new YGetPinsBuilder(api, storage).Build(null!).GetResponseAsync();
+ public Task GetAsync()
+ => new YGetPinsBuilder(Api).ExecuteAsync(null!);
}
\ No newline at end of file
diff --git a/YandexMusic.API/API/YPlaylistAPI.cs b/YandexMusic.API/API/YPlaylistAPI.cs
index 2005312..2387f77 100644
--- a/YandexMusic.API/API/YPlaylistAPI.cs
+++ b/YandexMusic.API/API/YPlaylistAPI.cs
@@ -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;
-/// API для взаимодействия с плейлистами.
+/// API для работы с плейлистами.
public class YPlaylistAPI : YCommonAPI
{
- /// Инициализирует новый экземпляр API плейлистов.
- /// Экземпляр основного API.
- public YPlaylistAPI(YandexMusicApi yandex) : base(yandex) { }
+ public YPlaylistAPI(YandexMusicApi api) : base(api) { }
- /// Получает список персональных плейлистов с главной страницы.
- /// Хранилище авторизации.
- /// Список ответов с плейлистами.
- public async Task>> GetPersonalPlaylistsAsync(AuthStorage storage)
+ public async Task> 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>();
+ return new List();
var tasks = block.Entities
.OfType()
- .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>(await Task.WhenAll(tasks));
+ var results = await Task.WhenAll(tasks);
+ return results.Where(p => p != null).ToList()!;
}
- /// Получает избранные плейлисты.
- public Task>> FavoritesAsync(AuthStorage storage)
- => new YGetPlaylistFavoritesBuilder(api, storage).Build(null!).GetResponseAsync();
+ public Task GetAsync(string user, string kind)
+ => new YGetPlaylistBuilder(Api).ExecuteAsync((user, kind));
- /// Получает плейлист дня.
- public Task> OfTheDayAsync(AuthStorage storage)
- => GetPersonalPlaylistAsync(storage, YGeneratedPlaylistType.PlaylistOfTheDay);
+ public Task GetAsync(string uuid)
+ => new YGetPlaylistByUuidBuilder(Api).ExecuteAsync(uuid);
- /// Получает плейлист «Дежавю».
- public Task> DejaVuAsync(AuthStorage storage)
- => GetPersonalPlaylistAsync(storage, YGeneratedPlaylistType.NeverHeard);
+ public Task GetAsync(YPlaylist playlist)
+ => GetAsync(playlist.Owner.Uid, playlist.Kind);
- /// Получает плейлист «Премьера».
- public Task> PremiereAsync(AuthStorage storage)
- => GetPersonalPlaylistAsync(storage, YGeneratedPlaylistType.RecentTracks);
+ public Task?> GetAsync(IEnumerable<(string user, string kind)> ids)
+ => new YGetPlaylistsBuilder(Api).ExecuteAsync(ids);
- /// Получает плейлист «Тайник».
- public Task> MissedAsync(AuthStorage storage)
- => GetPersonalPlaylistAsync(storage, YGeneratedPlaylistType.MissedLikes);
+ public Task?> FavoritesAsync()
+ => new YGetPlaylistFavoritesBuilder(Api).ExecuteAsync(null!);
- /// Получает плейлист «Кинопоиск».
- public Task> KinopoiskAsync(AuthStorage storage)
- => GetPersonalPlaylistAsync(storage, YGeneratedPlaylistType.Kinopoisk);
+ public async Task OfTheDayAsync()
+ => (await GetPersonalPlaylistsAsync()).FirstOrDefault(p => p?.GeneratedPlaylistType == YGeneratedPlaylistType.PlaylistOfTheDay.ToString());
- 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 async Task DejaVuAsync()
+ => (await GetPersonalPlaylistsAsync()).FirstOrDefault(p => p?.GeneratedPlaylistType == YGeneratedPlaylistType.NeverHeard.ToString());
- /// Получает плейлист по идентификатору пользователя и типа.
- public Task> GetAsync(AuthStorage storage, string user, string kind)
- => new YGetPlaylistBuilder(api, storage).Build((user, kind)).GetResponseAsync();
+ public async Task PremiereAsync()
+ => (await GetPersonalPlaylistsAsync()).FirstOrDefault(p => p?.GeneratedPlaylistType == YGeneratedPlaylistType.RecentTracks.ToString());
- /// Получает плейлист по UUID.
- public Task> GetAsync(AuthStorage storage, string uuid)
- => new YGetPlaylistByUuidBuilder(api, storage).Build(uuid).GetResponseAsync();
+ public async Task MissedAsync()
+ => (await GetPersonalPlaylistsAsync()).FirstOrDefault(p => p?.GeneratedPlaylistType == YGeneratedPlaylistType.MissedLikes.ToString());
- /// Получает несколько плейлистов по списку пар (пользователь, тип).
- public Task>> GetAsync(AuthStorage storage, IEnumerable<(string user, string kind)> ids)
- => new YGetPlaylistsBuilder(api, storage).Build(ids).GetResponseAsync();
+ public async Task KinopoiskAsync()
+ => (await GetPersonalPlaylistsAsync()).FirstOrDefault(p => p?.GeneratedPlaylistType == YGeneratedPlaylistType.Kinopoisk.ToString());
- /// Получает плейлист по объекту плейлиста (обновляет его треки).
- public Task> GetAsync(AuthStorage storage, YPlaylist playlist)
- => new YGetPlaylistBuilder(api, storage).Build((playlist.Owner.Uid, playlist.Kind)).GetResponseAsync();
+ public Task CreateAsync(string name)
+ => new YPlaylistCreateBuilder(Api).ExecuteAsync(name);
- /// Создаёт новый плейлист с заданным именем.
- public Task> CreateAsync(AuthStorage storage, string name)
- => new YPlaylistCreateBuilder(api, storage).Build(name).GetResponseAsync();
+ public Task RenameAsync(string kind, string name)
+ => new YPlaylistRenameBuilder(Api).ExecuteAsync((kind, name));
- /// Переименовывает плейлист.
- public Task> RenameAsync(AuthStorage storage, string kind, string name)
- => new YPlaylistRenameBuilder(api, storage).Build((kind, name)).GetResponseAsync();
+ public Task RenameAsync(YPlaylist playlist, string name)
+ => RenameAsync(playlist.Kind, name);
- /// Переименовывает плейлист.
- public Task> RenameAsync(AuthStorage storage, YPlaylist playlist, string name)
- => RenameAsync(storage, playlist.Kind, name);
-
- /// Удаляет плейлист.
- public async Task DeleteAsync(AuthStorage storage, string kind)
+ public async Task 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;
}
}
- /// Удаляет плейлист.
- public Task DeleteAsync(AuthStorage storage, YPlaylist playlist)
- => DeleteAsync(storage, playlist.Kind);
+ public Task DeleteAsync(YPlaylist playlist)
+ => DeleteAsync(playlist.Kind);
- /// Добавляет треки в начало плейлиста.
- public async Task> InsertTracksAsync(AuthStorage storage, YPlaylist playlist, IEnumerable tracks)
+ public async Task InsertTracksAsync(YPlaylist playlist, IEnumerable tracks)
{
- var change = await ChangePlaylistAsync(storage, playlist, new List
+ 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;
}
- /// Удаляет треки из плейлиста.
- public Task> DeleteTracksAsync(AuthStorage storage, YPlaylist playlist, IEnumerable tracks)
+ public async Task DeleteTracksAsync(YPlaylist playlist, IEnumerable 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 { 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> ChangePlaylistAsync(AuthStorage storage, YPlaylist playlist, IEnumerable 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;
+ }
}
\ No newline at end of file
diff --git a/YandexMusic.API/API/YQueueAPI.cs b/YandexMusic.API/API/YQueueAPI.cs
index f7881cf..8a016e6 100644
--- a/YandexMusic.API/API/YQueueAPI.cs
+++ b/YandexMusic.API/API/YQueueAPI.cs
@@ -1,72 +1,22 @@
-using YandexMusic.API.Common;
-using YandexMusic.API.Models.Common;
using YandexMusic.API.Models.Queue;
using YandexMusic.API.Requests.Queue;
namespace YandexMusic.API;
-///
-/// API для взаимодействия с очередями
-///
-public partial class YQueueAPI : YCommonAPI
+/// API для работы с очередями воспроизведения.
+public class YQueueAPI : YCommonAPI
{
- public YQueueAPI(YandexMusicApi yandex) : base(yandex)
- {
- }
+ public YQueueAPI(YandexMusicApi api) : base(api) { }
- ///
- /// Получение всех очередей треков с разных устройств для синхронизации между ними
- ///
- /// Хранилище
- /// Устройство
- ///
- public Task> ListAsync(AuthStorage storage, string? device = null)
- {
- return new YQueuesListBuilder(api, storage)
- .Build(device)
- .GetResponseAsync();
- }
+ public Task ListAsync(string? device = null)
+ => new YQueuesListBuilder(Api, device).ExecuteAsync(null!);
- ///
- /// Получение очереди
- ///
- /// Хранилище
- /// Идентификатор очереди
- ///
- public Task> GetAsync(AuthStorage storage, string queueId)
- {
- return new YGetQueueBuilder(api, storage)
- .Build(queueId)
- .GetResponseAsync();
- }
+ public Task GetAsync(string queueId)
+ => new YGetQueueBuilder(Api).ExecuteAsync(queueId);
- ///
- /// Создание новой очереди треков
- ///
- /// Хранилище
- /// Очередь треков
- /// Устройство
- ///
- public Task> CreateAsync(AuthStorage storage, YQueue queue, string? device = null)
- {
- return new YQueueCreateBuilder(api, storage, device)
- .Build(queue)
- .GetResponseAsync();
- }
+ public Task CreateAsync(YQueue queue, string? device = null)
+ => new YQueueCreateBuilder(Api, device).ExecuteAsync(queue);
- ///
- /// Установка текущего индекса проигрываемого трека в очереди треков
- ///
- /// Хранилище
- /// Идентификатор очереди
- /// Текущий индекс
- /// Флаг интерактивности
- /// Устройство
- ///
- public Task> UpdatePositionAsync(AuthStorage storage, string queueId, int currentIndex, bool isInteractive, string device = null)
- {
- return new YQueueUpdatePositionBuilder(api, storage, device)
- .Build((queueId, currentIndex, isInteractive))
- .GetResponseAsync();
- }
-}
+ public Task UpdatePositionAsync(string queueId, int currentIndex, bool isInteractive, string? device = null)
+ => new YQueueUpdatePositionBuilder(Api, device).ExecuteAsync((queueId, currentIndex, isInteractive));
+}
\ No newline at end of file
diff --git a/YandexMusic.API/API/YRadioAPI.cs b/YandexMusic.API/API/YRadioAPI.cs
index 02172bc..e13611d 100644
--- a/YandexMusic.API/API/YRadioAPI.cs
+++ b/YandexMusic.API/API/YRadioAPI.cs
@@ -1,113 +1,37 @@
-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;
-///
-/// API для взаимодействия с радио
-///
-public partial class YRadioAPI : YCommonAPI
+/// API для работы с радио.
+public class YRadioAPI : YCommonAPI
{
- public YRadioAPI(YandexMusicApi yandex) : base(yandex)
- {
- }
+ public YRadioAPI(YandexMusicApi api) : base(api) { }
- ///
- /// Получение списка рекомендованных радиостанций
- ///
- /// Хранилище
- ///
- public Task> GetStationsDashboardAsync(AuthStorage storage)
- {
- return new YGetStationsDashboardBuilder(api, storage)
- .Build(null)
- .GetResponseAsync();
- }
+ public Task GetStationsDashboardAsync()
+ => new YGetStationsDashboardBuilder(Api).ExecuteAsync(null!);
- ///
- /// Получение списка радиостанций
- ///
- /// Хранилище
- ///
- public Task>> GetStationsAsync(AuthStorage storage)
- {
- return new YGetStationsBuilder(api, storage)
- .Build(null)
- .GetResponseAsync();
- }
+ public Task?> GetStationsAsync()
+ => new YGetStationsBuilder(Api).ExecuteAsync(null!);
- ///
- /// Получение информации о радиостанции
- ///
- /// Хранилище
- /// Тип
- /// Тэг
- ///
- public Task>> GetStationAsync(AuthStorage storage, string type, string tag)
- {
- return new YGetStationBuilder(api, storage)
- .Build((type, tag))
- .GetResponseAsync();
- }
+ public Task?> GetStationAsync(string type, string tag)
+ => new YGetStationBuilder(Api).ExecuteAsync((type, tag));
- ///
- /// Получение информации о радиостанции
- ///
- /// Хранилище
- /// Идентификатор станции
- ///
- public Task>> GetStationAsync(AuthStorage storage, YStationId id)
- {
- return GetStationAsync(storage, id.Type, id.Tag);
- }
+ public Task?> GetStationAsync(YStationId id)
+ => GetStationAsync(id.Type, id.Tag);
- ///
- /// Получение последовательности треков радиостанции
- ///
- /// Хранилище
- /// Радиостанция
- /// Идентификатор предыдущего трека
- ///
- public Task> GetStationTracksAsync(AuthStorage storage, YStation station, string prevTrackId = "")
- {
- return new YGetStationTracksBuilder(api, storage)
- .Build((station.Station, prevTrackId))
- .GetResponseAsync();
- }
-
- ///
- /// Установка настроек подбора треков
- ///
- /// Хранилище
- /// Радиостанция
- /// Настройки
- ///
- public Task> SetStationSettings2Async(AuthStorage storage, YStation station, YStationSettings2 settings)
- {
- return new YSetSettings2Builder(api, storage)
- .Build((station.Station, settings))
- .GetResponseAsync();
- }
-
- ///
- /// Отправка обратной связи на действия при прослушивании радио
- ///
- /// Хранилище
- /// Радиостанция
- /// Тип обратной связи
- /// Трек
- /// Уникальный идентификатор партии треков. Возвращается при получении треков
- /// Сколько было проиграно секунд трека перед действием
- ///
- public Task 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();
- }
+ public Task GetStationTracksAsync(YStation station, string prevTrackId = "")
+ => new YGetStationTracksBuilder(Api).ExecuteAsync((station.Station, prevTrackId));
+ public Task SetStationSettings2Async(YStation station, YStationSettings2 settings)
+ => new YSetSettings2Builder(Api).ExecuteAsync((station.Station, settings));
+ public Task SendStationFeedbackAsync(
+ YStation station,
+ YStationFeedbackType type,
+ YTrack? track = null,
+ string batchId = "",
+ double totalPlayedSeconds = 0)
+ => new YSetStationFeedbackBuilder(Api).ExecuteAsync((type, station, track, batchId, totalPlayedSeconds));
}
\ No newline at end of file
diff --git a/YandexMusic.API/API/YSearchAPI.cs b/YandexMusic.API/API/YSearchAPI.cs
index 1a9a690..c4d5803 100644
--- a/YandexMusic.API/API/YSearchAPI.cs
+++ b/YandexMusic.API/API/YSearchAPI.cs
@@ -1,139 +1,38 @@
-using YandexMusic.API.Common;
using YandexMusic.API.Models.Common;
using YandexMusic.API.Models.Search;
using YandexMusic.API.Requests.Search;
namespace YandexMusic.API;
-///
-/// API для поиска
-///
-public partial class YSearchAPI : YCommonAPI
+/// API для поиска.
+public class YSearchAPI : YCommonAPI
{
+ public YSearchAPI(YandexMusicApi api) : base(api) { }
- public YSearchAPI(YandexMusicApi yandex) : base(yandex)
- {
- }
+ public Task TrackAsync(string trackName, int page = 0, int pageSize = 20)
+ => SearchAsync(trackName, YSearchType.Track, page, pageSize);
- ///
- /// Поиск по трекам
- ///
- /// Хранилище
- /// Имя трека
- /// Номер страницы
- /// Размер страницы
- ///
- public Task> TrackAsync(AuthStorage storage, string trackName, int pageNumber = 0, int pageSize = 20)
- {
- return SearchAsync(storage, trackName, YSearchType.Track, pageNumber, pageSize);
- }
+ public Task AlbumsAsync(string albumName, int page = 0, int pageSize = 20)
+ => SearchAsync(albumName, YSearchType.Album, page, pageSize);
- ///
- /// Поиск по альбомам
- ///
- /// Хранилище
- /// Имя альбома
- /// Номер страницы
- /// Размер страницы
- ///
- public Task> AlbumsAsync(AuthStorage storage, string albumName, int pageNumber = 0, int pageSize = 20)
- {
- return SearchAsync(storage, albumName, YSearchType.Album, pageNumber, pageSize);
- }
+ public Task ArtistAsync(string artistName, int page = 0, int pageSize = 20)
+ => SearchAsync(artistName, YSearchType.Artist, page, pageSize);
- ///
- /// Поиск по артисту
- ///
- /// Хранилище
- /// Имя артиста
- /// Номер страницы
- /// Размер страницы
- ///
- public Task> ArtistAsync(AuthStorage storage, string artistName, int pageNumber = 0, int pageSize = 20)
- {
- return SearchAsync(storage, artistName, YSearchType.Artist, pageNumber, pageSize);
- }
+ public Task PlaylistAsync(string playlistName, int page = 0, int pageSize = 20)
+ => SearchAsync(playlistName, YSearchType.Playlist, page, pageSize);
- ///
- /// Поиск по плейлистам
- ///
- /// Хранилище
- /// Имя плейлиста
- /// Номер страницы
- /// Размер страницы
- ///
- public Task> PlaylistAsync(AuthStorage storage, string playlistName, int pageNumber = 0, int pageSize = 20)
- {
- return SearchAsync(storage, playlistName, YSearchType.Playlist, pageNumber, pageSize);
- }
+ public Task PodcastEpisodeAsync(string podcastName, int page = 0, int pageSize = 20)
+ => SearchAsync(podcastName, YSearchType.PodcastEpisode, page, pageSize);
- ///
- /// Поиск по плейлистам
- ///
- /// Хранилище
- /// Имя подкаста
- /// Номер страницы
- /// Размер страницы
- ///
- public Task> PodcastEpisodeAsync(AuthStorage storage, string podcastName, int pageNumber = 0, int pageSize = 20)
- {
- return SearchAsync(storage, podcastName, YSearchType.PodcastEpisode, pageNumber, pageSize);
- }
+ public Task VideosAsync(string videoName, int page = 0, int pageSize = 20)
+ => SearchAsync(videoName, YSearchType.Video, page, pageSize);
- ///
- /// Поиск по видео
- ///
- /// Хранилище
- /// Имя видео
- /// Номер страницы
- /// Размер страницы
- ///
- public Task> VideosAsync(AuthStorage storage, string videoName, int pageNumber = 0, int pageSize = 20)
- {
- return SearchAsync(storage, videoName, YSearchType.Video, pageNumber, pageSize);
- }
-
- ///
- /// Поиск по пользователям
- ///
- /// Хранилище
- /// Имя пользователя
- /// Номер страницы
- /// Размер страницы
- ///
- public Task> UsersAsync(AuthStorage storage, string userName, int pageNumber = 0, int pageSize = 20)
- {
- return SearchAsync(storage, userName, YSearchType.User, pageNumber, pageSize);
- }
-
- ///
- /// Поиск
- ///
- /// Хранилище
- /// Поисковый запрос
- /// Тип поиска
- /// Страница
- /// Размер страницы
- ///
- public Task> SearchAsync(AuthStorage storage, string searchText, YSearchType searchType, int page = 0, int pageSize = 20)
- {
- return new YSearchBuilder(api, storage)
- .Build((searchText, searchType, page, pageSize))
- .GetResponseAsync();
- }
-
- ///
- /// Подсказка
- ///
- /// Хранилище
- /// Поисковый запрос
- ///
- public Task> SuggestAsync(AuthStorage storage, string searchText)
- {
- return new YSearchSuggestBuilder(api, storage)
- .Build(searchText)
- .GetResponseAsync();
- }
+ public Task UsersAsync(string userName, int page = 0, int pageSize = 20)
+ => SearchAsync(userName, YSearchType.User, page, pageSize);
+ public Task SearchAsync(string searchText, YSearchType searchType, int page = 0, int pageSize = 20)
+ => new YSearchBuilder(Api).ExecuteAsync((searchText, searchType, page, pageSize));
+ public Task GetSearchSuggestionsAsync(string searchText)
+ => new YSearchSuggestBuilder(Api).ExecuteAsync(searchText);
}
\ No newline at end of file
diff --git a/YandexMusic.API/API/YTrackAPI.cs b/YandexMusic.API/API/YTrackAPI.cs
index f495dd6..290cdd4 100644
--- a/YandexMusic.API/API/YTrackAPI.cs
+++ b/YandexMusic.API/API/YTrackAPI.cs
@@ -1,307 +1,110 @@
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;
-///
-/// API для взаимодействия с треками
-///
-public partial class YTrackAPI : YCommonAPI
+/// API для работы с треками (получение, загрузка, метаданные).
+public class YTrackAPI : YCommonAPI
{
- #region Вспомогательные функции
+ public YTrackAPI(YandexMusicApi api) : base(api) { }
- private string BuildLinkForDownload(YTrackDownloadInfo mainDownloadResponse, YStorageDownloadFile storageDownload)
+ private static string BuildDownloadLink(YTrackDownloadInfo info, YStorageDownloadFile storageDownload)
{
- string path = storageDownload.Path;
- string host = storageDownload.Host;
- string ts = storageDownload.Ts;
- string s = storageDownload.S;
- string codec = mainDownloadResponse.Codec;
+ var path = storageDownload.Path;
+ var host = storageDownload.Host;
+ var ts = storageDownload.Ts;
+ var s = storageDownload.S;
+ var codec = info.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;
+ var secret = $"XGRlBW9FXlekgbPrRHuSiA{path[1..]}{s}";
+ var md5Hash = MD5.HashData(Encoding.UTF8.GetBytes(secret));
+ var hmacsha1 = new HMACSHA1(md5Hash);
+ var sign = BitConverter.ToString(hmacsha1.ComputeHash(md5Hash)).Replace("-", "").ToLower();
+ return $"https://{host}/get-{codec}/{sign}/{ts}{path}";
}
- #endregion Вспомогательные функции
+ public Task GetAsync(string trackId)
+ => GetAsync(trackId);
+ public Task?> GetAsync(IEnumerable trackIds)
+ => new YGetTracksBuilder(Api).ExecuteAsync(trackIds);
+ public Task?> GetMetadataForDownloadAsync(string trackKey, bool direct = false)
+ => new YTrackDownloadInfoBuilder(Api).ExecuteAsync((trackKey, direct));
+ public Task?> GetMetadataForDownloadAsync(YTrack track, bool direct = false)
+ => GetMetadataForDownloadAsync(track.GetKey().ToString(), direct);
- public YTrackAPI(YandexMusicApi yandex) : base(yandex)
+ public Task GetDownloadFileInfoAsync(YTrackDownloadInfo metadataInfo)
+ => new YStorageDownloadFileBuilder(Api).ExecuteAsync(metadataInfo.DownloadInfoUrl);
+
+ public async Task GetFileLinkAsync(string trackKey)
{
+ var meta = await GetMetadataForDownloadAsync(trackKey);
+ var info = meta?.OrderByDescending(i => i.BitrateInKbps).FirstOrDefault(m => m.Codec == "mp3");
+ if (info == null) return null;
+ var storageDownload = await GetDownloadFileInfoAsync(info);
+ if (storageDownload == null) return null;
+ return BuildDownloadLink(info, storageDownload);
}
- ///
- /// Получение треков
- ///
- /// Хранилище
- /// Идентификатор трека
- ///
- public Task>> GetAsync(AuthStorage storage, string trackId)
+ public Task GetFileLinkAsync(YTrack track)
+ => GetFileLinkAsync(track.GetKey().ToString());
+
+ public async Task ExtractToFileAsync(string trackKey, string filePath)
{
- return new YGetTracksBuilder(api, storage)
- .Build(new[] { trackId })
- .GetResponseAsync();
+ var url = await GetFileLinkAsync(trackKey);
+ if (string.IsNullOrEmpty(url)) throw new Exception("Не удалось получить ссылку на трек");
+ using var response = await Api.HttpClient.GetAsync(url);
+ await using var fs = File.Create(filePath);
+ await response.Content.CopyToAsync(fs);
}
- ///
- /// Получение треков
- ///
- /// Хранилище
- /// Идентификаторы треков
- ///
- public Task>> GetAsync(AuthStorage storage, IEnumerable trackIds)
+ public Task ExtractToFileAsync(YTrack track, string filePath)
+ => ExtractToFileAsync(track.GetKey().ToString(), filePath);
+
+ public async Task ExtractDataAsync(string trackKey)
{
- return new YGetTracksBuilder(api, storage)
- .Build(trackIds)
- .GetResponseAsync();
+ var url = await GetFileLinkAsync(trackKey);
+ if (string.IsNullOrEmpty(url)) throw new Exception("Не удалось получить ссылку на трек");
+ return await Api.HttpClient.GetByteArrayAsync(url);
}
- ///
- /// Получение метаданных для загрузки
- ///
- /// Хранилище
- /// Ключ трека в формате {идентифактор трека:идентификатор альбома}
- /// Должен ли ответ содержать прямую ссылку на загрузку
- ///
- public Task>> GetMetadataForDownloadAsync(AuthStorage storage, string trackKey, bool direct = false)
+ public Task ExtractDataAsync(YTrack track)
+ => ExtractDataAsync(track.GetKey().ToString());
+
+ public async Task ExtractStreamAsync(string trackKey, HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead)
{
- return new YTrackDownloadInfoBuilder(api, storage)
- .Build((trackKey, direct))
- .GetResponseAsync();
+ var url = await GetFileLinkAsync(trackKey);
+ if (string.IsNullOrEmpty(url)) throw new Exception("Не удалось получить ссылку на трек");
+ var response = await Api.HttpClient.GetAsync(url, completionOption);
+ return await response.Content.ReadAsStreamAsync();
}
- ///
- /// Получение метаданных для загрузки
- ///
- /// Хранилище
- /// Трек
- /// Должен ли ответ содержать прямую ссылку на загрузку
- ///
- public Task>> GetMetadataForDownloadAsync(AuthStorage storage, YTrack track, bool direct = false)
- {
- return GetMetadataForDownloadAsync(storage, track.GetKey().ToString(), direct);
- }
+ public Task ExtractStreamAsync(YTrack track, HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead)
+ => ExtractStreamAsync(track.GetKey().ToString(), completionOption);
- ///
- /// Получение информации для формирования ссылки для загрузки
- ///
- /// Хранилище
- /// Метаданные для загрузки
- ///
- public Task GetDownloadFileInfoAsync(AuthStorage storage, YTrackDownloadInfo metadataInfo)
- {
- return new YStorageDownloadFileBuilder(api, storage)
- .Build(metadataInfo.DownloadInfoUrl)
- .GetResponseAsync();
- }
+ public Task SendPlayTrackInfoAsync(
+ YTrack track,
+ string from,
+ bool fromCache = false,
+ string playId = "",
+ string playlistId = "",
+ double totalPlayedSeconds = 0,
+ double endPositionSeconds = 0)
+ => new YSendTrackInfoBuilder(Api).ExecuteAsync((track, from, fromCache, playId, playlistId, totalPlayedSeconds, endPositionSeconds));
- ///
- /// Получение ссылки для загрузки
- ///
- /// Хранилище
- /// Ключ трека в формате {идентификатор трека:идентификатор альбома}
- ///
- public async Task GetFileLinkAsync(AuthStorage storage, string trackKey)
- {
- YResponse> 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);
- }
+ public Task GetSupplementAsync(string trackId)
+ => new YGetTrackSupplementBuilder(Api).ExecuteAsync(trackId);
- ///
- /// Получение ссылки для загрузки
- ///
- /// Хранилище
- /// Трек
- ///
- public Task GetFileLinkAsync(AuthStorage storage, YTrack track)
- {
- return GetFileLinkAsync(storage, track.GetKey().ToString());
- }
-
- ///
- /// Отправка текущего состояния прослушиваемого трека
- /// Хранилище
- /// Трек
- /// Наименования клиента, с которого происходит прослушивание
- /// Проигрывается ли трек с кеша
- /// Уникальный идентификатор проигрывания
- /// Уникальный идентификатор плейлиста, если таковой прослушивается
- /// Сколько было всего воспроизведено трека в секундах
- /// Окончательное значение воспроизведенных секунд
- ///
- ///
- public Task 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
-
- ///
- /// Получение дополнительной информации для трека
- ///
- /// Хранилище
- /// Идентификатор трека
- ///
- public Task> GetSupplementAsync(AuthStorage storage, string trackId)
- {
- return new YGetTrackSupplementBuilder(api, storage)
- .Build(trackId)
- .GetResponseAsync();
- }
-
- ///
- /// Получение дополнительной информации для трека
- ///
- /// Хранилище
- /// Трек
- ///
- public Task> GetSupplementAsync(AuthStorage storage, YTrack track)
- {
- return new YGetTrackSupplementBuilder(api, storage)
- .Build(track.GetKey().ToString())
- .GetResponseAsync();
- }
-
- #endregion GetSupplement
-
- #region GetSimilar
-
- ///
- /// Получение похожих треков
- ///
- /// Хранилище
- /// Идентификатор трека
- ///
- public Task> GetSimilarAsync(AuthStorage storage, string trackId)
- {
- return new YGetTrackSimilarBuilder(api, storage)
- .Build(trackId)
- .GetResponseAsync();
- }
-
- ///
- /// Получение похожих треков
- ///
- /// Хранилище
- /// Трек
- ///
- public Task> GetSimilarAsync(AuthStorage storage, YTrack track)
- {
- return new YGetTrackSimilarBuilder(api, storage)
- .Build(track.GetKey().ToString())
- .GetResponseAsync();
- }
-
- #endregion GetSimilar
-
- #region Получение данных трека
-
- #region В файл
-
- ///
- /// Выгрузка в файл
- ///
- /// Хранилище
- /// Ключ трека в формате {идентификатор трека:идентификатор альбома}
- /// Путь для файла
- public async Task ExtractToFileAsync(AuthStorage storage, string trackKey, string filePath)
- {
- string url = await GetFileLinkAsync(storage, trackKey);
- await new DataDownloader(storage).ToFile(url, filePath);
- }
-
- ///
- /// Выгрузка в файл
- ///
- /// Хранилище
- /// Трек
- /// Путь для файла
- public Task ExtractToFileAsync(AuthStorage storage, YTrack track, string filePath)
- {
- return ExtractToFileAsync(storage, track.GetKey().ToString(), filePath);
- }
-
- #endregion В файл
-
- #region В массив байт
-
- ///
- /// Получение двоичного массива данных
- ///
- /// Хранилище
- /// Ключ трека в формате {идентификатор трека:идентификатор альбома}
- ///
- public async Task ExtractDataAsync(AuthStorage storage, string trackKey)
- {
- string url = await GetFileLinkAsync(storage, trackKey);
- return await new DataDownloader(storage).AsBytes(url);
- }
-
- ///
- /// Получение двоичного массива данных
- ///
- /// Хранилище
- /// Трек
- ///
- public Task ExtractDataAsync(AuthStorage storage, YTrack track)
- {
- return ExtractDataAsync(storage, track.GetKey().ToString());
- }
-
- #endregion В массив байт
-
- #region В поток
-
- ///
- /// Получение потока данных
- ///
- /// Хранилище
- /// Ключ трека в формате {идентификатор трека:идентификатор альбома}
- /// Параметры передачи управления при http запросе
- ///
- public async Task ExtractStreamAsync(AuthStorage storage, string trackKey,
- HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead)
- {
- string url = await GetFileLinkAsync(storage, trackKey);
- return await new DataDownloader(storage).AsStream(url, httpCompletionOption);
- }
-
- ///
- /// Получение потока данных
- ///
- /// Хранилище
- /// Трек
- /// Параметры передачи управления при http запросе
- ///
- public Task ExtractStreamAsync(AuthStorage storage, YTrack track,
- HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead)
- {
- return ExtractStreamAsync(storage, track.GetKey().ToString(), httpCompletionOption);
- }
-
- #endregion В поток
-
- #endregion Получение данных трека
+ public Task GetSupplementAsync(YTrack track)
+ => GetSupplementAsync(track.GetKey().ToString());
+ public Task GetSimilarAsync(string trackId)
+ => new YGetTrackSimilarBuilder(Api).ExecuteAsync(trackId);
+ public Task GetSimilarAsync(YTrack track)
+ => GetSimilarAsync(track.GetKey().ToString());
}
\ No newline at end of file
diff --git a/YandexMusic.API/API/YUgcAPI.cs b/YandexMusic.API/API/YUgcAPI.cs
index bc6536c..5f4ae6a 100644
--- a/YandexMusic.API/API/YUgcAPI.cs
+++ b/YandexMusic.API/API/YUgcAPI.cs
@@ -1,71 +1,36 @@
-using YandexMusic.API.Common;
-using YandexMusic.API.Models.Common;
-using YandexMusic.API.Models.Playlist;
+using YandexMusic.API.Models.Playlist;
using YandexMusic.API.Models.Ugc;
using YandexMusic.API.Requests.Ugc;
namespace YandexMusic.API;
-public partial class YUgcAPI : YCommonAPI
+/// API для загрузки пользовательского контента (UGC).
+public class YUgcAPI : YCommonAPI
{
- public YUgcAPI(YandexMusicApi yandex) : base(yandex)
- {
- }
+ public YUgcAPI(YandexMusicApi api) : base(api) { }
- ///
- /// Получение ссылки на загрузчик трека
- ///
- /// Хранилище
- /// Плейлист, куда будет загружен трек
- /// Название файла для загрузки
- public Task GetUgcUploadLinkAsync(AuthStorage storage, YPlaylist playlist, string fileName)
- {
- return new YUgcGetUploadLinkBuilder(api, storage)
- .Build((playlist, fileName))
- .GetResponseAsync();
- }
+ public Task GetUgcUploadLinkAsync(YPlaylist playlist, string fileName)
+ => new YUgcGetUploadLinkBuilder(Api).ExecuteAsync((playlist, fileName));
- ///
- /// Загрузка трека из файла
- ///
- /// Хранилище
- /// Ссылка на балансировщик для загрузки, можно получить из GetUgcUploadLinkAsync
- /// Загружаемый файл
- public Task> UploadUgcTrackAsync(AuthStorage storage, string uploadLink, string filePath)
+ public async Task UploadTrackToPlaylistAsync(YPlaylist playlist, string fileName, string filePath)
{
if (!File.Exists(filePath))
- throw new FileNotFoundException("Файл для загрузки не существует.", filePath);
-
- return UploadUgcTrackAsync(storage, uploadLink, File.Open(filePath, FileMode.Open));
+ throw new FileNotFoundException("Файл не найден", filePath);
+ return await UploadTrackToPlaylistAsync(playlist, fileName, await File.ReadAllBytesAsync(filePath));
}
- ///
- /// Загрузка трека из потока
- ///
- /// Хранилище
- /// Ссылка на балансировщик для загрузки, можно получить из GetUgcUploadLinkAsync
- /// Поток с данными для загрузки
- public Task> UploadUgcTrackAsync(AuthStorage storage, string uploadLink, Stream stream)
+ public async Task UploadTrackToPlaylistAsync(YPlaylist playlist, string fileName, Stream stream)
{
- if (stream == null)
- throw new NullReferenceException("Пустая ссылка на поток загрузки.");
-
- using MemoryStream ms = new();
- stream.CopyTo(ms);
-
- return UploadUgcTrackAsync(storage, uploadLink, ms.ToArray());
+ using var ms = new MemoryStream();
+ await stream.CopyToAsync(ms);
+ return await UploadTrackToPlaylistAsync(playlist, fileName, ms.ToArray());
}
- ///
- /// Загрузка трека из массива
- ///
- /// Хранилище
- /// Ссылка на балансировщик для загрузки, можно получить из GetUgcUploadLinkAsync
- /// Загружаемый трек в виде массив байтов
- public Task> UploadUgcTrackAsync(AuthStorage storage, string uploadLink, byte[] file)
+ public async Task UploadTrackToPlaylistAsync(YPlaylist playlist, string fileName, byte[] file)
{
- return new YUgcUploadBuilder(api, storage)
- .Build((uploadLink, file))
- .GetResponseAsync();
+ var uploadLink = await GetUgcUploadLinkAsync(playlist, fileName);
+ if (uploadLink?.PostTarget == null) return null;
+ var result = await new YUgcUploadBuilder(Api).ExecuteAsync((uploadLink.PostTarget, file));
+ return result?.Result;
}
}
\ No newline at end of file
diff --git a/YandexMusic.API/API/YUserAPI.cs b/YandexMusic.API/API/YUserAPI.cs
index d66d638..140e60f 100644
--- a/YandexMusic.API/API/YUserAPI.cs
+++ b/YandexMusic.API/API/YUserAPI.cs
@@ -1,300 +1,159 @@
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;
-///
-/// API для пользователя
-///
-public partial class YUserAPI : YCommonAPI
+/// API для работы с пользователем и авторизации.
+public class YUserAPI : YCommonAPI
{
- #region Вспомогательные функции
+ public YUserAPI(YandexMusicApi api) : base(api) { }
- private async Task GetCsrfTokenAsync(AuthStorage storage)
+ private async Task GetCsrfTokenAsync()
{
- using HttpResponseMessage authMethodsResponse = await new YGetAuthMethodsBuilder(api, storage)
- .Build(null)
- .GetResponseAsync();
+ using var response = await new YGetAuthMethodsBuilder(Api).ExecuteRawAsync(null!);
+ if (response == null || !response.IsSuccessStatusCode)
+ throw new HttpRequestException("Не удалось получить CSRF-токен");
- if (!authMethodsResponse.IsSuccessStatusCode)
- throw new HttpRequestException("Невозможно получить CFRF-токен.");
+ var content = await response.Content.ReadAsStringAsync();
+ var csrfMatch = Regex.Match(content, @"window\.__CSRF__\s*=\s*""([^""]+)""");
+ var processMatch = Regex.Match(content, @"'process_uuid'\s*:\s*'([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})'");
- string responseString = await authMethodsResponse.Content
- .ReadAsStringAsync();
- Match match = Regex.Match(responseString, "\"csrf_token\" value=\"([^\"]+)\"");
-
- if (!match.Success || match.Groups.Count < 2)
+ if (!csrfMatch.Success || !processMatch.Success)
return false;
- storage.AuthToken = new YAuthToken
+ Api.Storage.AuthToken = new YAuthToken
{
- CsfrToken = match.Groups[1].Value
+ CsfrToken = csrfMatch.Groups[1].Value,
+ ProcessUuid = processMatch.Groups[1].Value
};
+ await new YPostAuthStats(Api).ExecuteAsync(null!);
+ return true;
+ }
+
+ private async Task LoginByCookiesAsync()
+ {
+ if (Api.Storage.AuthToken == null)
+ throw new AuthenticationException("Сессия входа не инициализирована");
+
+ var accessToken = await new YGetAuthCookiesBuilder(Api).ExecuteAsync(null!);
+ if (accessToken == null || string.IsNullOrEmpty(accessToken.AccessToken))
+ return false;
+
+ Api.Storage.AccessToken = accessToken;
+ Api.Storage.Token = accessToken.AccessToken;
+
+ var shortInfo = await new YGetShortAccountInfoBuilder(Api).ExecuteAsync(null!);
+ if (shortInfo?.Status != YAuthStatus.Ok || string.IsNullOrWhiteSpace(shortInfo.Uid))
+ throw new Exception("Не удалось подтвердить авторизацию");
+
return true;
}
- private async Task 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)
- {
- }
-
- ///
- /// Авторизация
- ///
- /// Хранилище
- /// Токен авторизации
- ///
- public async Task AuthorizeAsync(AuthStorage storage, string token)
+ public async Task AuthorizeAsync(string token)
{
if (string.IsNullOrEmpty(token))
- throw new Exception("Задан пустой токен авторизации.");
+ throw new Exception("Токен не может быть пустым");
- storage.Token = token;
+ Api.Storage.Token = token;
+ var authInfo = await new YGetAuthInfoBuilder(Api).ExecuteAsync(null!);
+ if (authInfo?.Account?.Uid == null)
+ throw new Exception("Пользователь не авторизован");
- // Пытаемся получить информацию о пользователе
- YResponse authInfo = await GetUserAuthAsync(storage);
-
- // Если не авторизован, то авторизуем
- if (string.IsNullOrEmpty(authInfo.Result.Account.Uid))
- throw new Exception("Пользователь незалогинен.");
-
- // Флаг авторизации
- storage.IsAuthorized = true;
- storage.User = authInfo.Result.Account;
+ Api.Storage.SetAuthorized(authInfo.Account, token);
}
- ///
- /// Получение информации об авторизации
- ///
- /// Хранилище
- ///
- public Task> GetUserAuthAsync(AuthStorage storage)
+ public Task GetUserAuthAsync()
+ => new YGetAuthInfoBuilder(Api).ExecuteAsync(null!);
+
+ public async Task CreateAuthSessionAsync(string userName)
{
- return new YGetAuthInfoBuilder(api, storage)
- .Build(null)
- .GetResponseAsync();
+ if (!await GetCsrfTokenAsync())
+ throw new Exception("Не удалось инициализировать сессию");
+
+ var result = await new YGetAuthLoginUserBuilder(Api).ExecuteAsync((Api.Storage.AuthToken.CsfrToken, userName));
+ if (result?.TrackId != null)
+ Api.Storage.AuthToken.TrackId = result.TrackId;
+ return result;
}
- ///
- /// Создание сеанса и получение доступных методов авторизации
- ///
- /// Хранилище
- /// Имя пользователя
- ///
- public async Task CreateAuthSessionAsync(AuthStorage storage, string userName)
+ public async Task GetAuthQRLinkAsync()
{
- if (!await GetCsrfTokenAsync(storage))
- throw new Exception("Невозможно инициализировать сессию входа.");
+ if (!await GetCsrfTokenAsync())
+ throw new Exception("Не удалось инициализировать сессию");
- YAuthTypes types = await new YGetAuthLoginUserBuilder(api, storage)
- .Build((storage.AuthToken.CsfrToken, userName))
- .GetResponseAsync();
+ var qr = await new YGetAuthQRBuilder(Api).ExecuteAsync(null!);
+ if (qr?.Status != YAuthStatus.Ok || string.IsNullOrEmpty(qr.TrackId))
+ return null;
- storage.AuthToken.TrackId = types.TrackId;
-
- return types;
- }
-
- ///
- /// Получение ссылки на QR-код
- ///
- /// Хранилище
- ///
- public async Task 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
+ Api.Storage.AuthToken = new YAuthToken
{
- TrackId = result.TrackId,
- CsfrToken = result.CsrfToken
+ TrackId = qr.TrackId,
+ CsfrToken = qr.CsrfToken
};
-
- return $"https://passport.yandex.ru/auth/magic/code/?track_id={result.TrackId}";
+ return $"https://passport.yandex.ru/auth/magic/code/?track_id={qr.TrackId}";
}
- ///
- /// Авторизация по QR-коду
- ///
- /// Хранилище
- ///
- public async Task AuthorizeByQRAsync(AuthStorage storage)
+ public async Task AuthorizeByQRAsync()
{
- if (storage.AuthToken == null)
- throw new Exception("Не выполнен запрос на авторизацию по QR.");
+ if (Api.Storage.AuthToken == null)
+ throw new Exception("Сессия не инициализирована");
- 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);
- }
+ var status = await new YGetAuthLoginQRBuilder(Api).ExecuteAsync(null!);
+ if (status?.Status == YAuthStatus.Ok && await LoginByCookiesAsync())
+ return status;
+ throw new AuthenticationException("Ошибка авторизации по QR");
}
- ///
- /// Получение
- ///
- /// Хранилище
- ///
- public Task GetCaptchaAsync(AuthStorage storage)
+ public Task GetCaptchaAsync()
{
- if (storage.AuthToken == null || string.IsNullOrWhiteSpace(storage.AuthToken.CsfrToken))
- throw new AuthenticationException($"Не найдена сессия входа. Выполните {nameof(CreateAuthSessionAsync)} перед использованием.");
-
- return new YGetAuthCaptchaBuilder(api, storage)
- .Build(null)
- .GetResponseAsync();
+ if (Api.Storage.AuthToken == null)
+ throw new AuthenticationException("Выполните CreateAuthSessionAsync перед использованием");
+ return new YGetAuthCaptchaBuilder(Api).ExecuteAsync(null!);
}
- ///
- /// Авторизация по captcha
- ///
- /// Хранилище
- /// Значение captcha
- ///
- public Task AuthorizeByCaptchaAsync(AuthStorage storage, string captchaValue)
+ public Task AuthorizeByCaptchaAsync(string captchaValue)
{
- if (storage.AuthToken == null || string.IsNullOrWhiteSpace(storage.AuthToken.CsfrToken))
- throw new AuthenticationException($"Не найдена сессия входа. Выполните {nameof(CreateAuthSessionAsync)} перед использованием.");
-
- return new YGetAuthLoginCaptchaBuilder(api, storage)
- .Build(captchaValue)
- .GetResponseAsync();
+ if (Api.Storage.AuthToken == null)
+ throw new AuthenticationException("Выполните CreateAuthSessionAsync перед использованием");
+ return new YGetAuthLoginCaptchaBuilder(Api).ExecuteAsync(captchaValue);
}
- ///
- /// Получение письма авторизации на почту пользователя
- ///
- /// Хранилище
- ///
- public Task GetAuthLetterAsync(AuthStorage storage)
+ public Task GetAuthLetterAsync()
+ => new YGetAuthLetterBuilder(Api).ExecuteAsync(null!);
+
+ public async Task AuthorizeByLetterAsync()
{
- return new YGetAuthLetterBuilder(api, storage)
- .Build(null)
- .GetResponseAsync();
+ var status = await new YGetAuthLoginLetterBuilder(Api).ExecuteAsync(null!);
+ if (status?.Status != YAuthStatus.Ok || !status.MagicLinkConfirmed)
+ throw new Exception("Письмо не подтверждено");
+ return await LoginByCookiesAsync();
}
- ///
- /// Авторизация после подтверждения входа через письмо
- ///
- /// Хранилище
- ///
- public async Task AuthorizeByLetterAsync(AuthStorage storage)
+ public async Task AuthorizeByAppPasswordAsync(string password)
{
- YAuthLetterStatus status = await new YGetAuthLoginLetterBuilder(api, storage)
- .Build(null)
- .GetResponseAsync();
+ if (Api.Storage.AuthToken == null)
+ throw new AuthenticationException("Выполните CreateAuthSessionAsync перед использованием");
- if (status.Status == YAuthStatus.Ok && !status.MagicLinkConfirmed)
- throw new Exception("Не подтвержден вход посредством e-mail.");
-
- return await LoginByCookiesAsync(storage);
+ var result = await new YGetAuthAppPasswordBuilder(Api).ExecuteAsync(password);
+ if (result?.Status == YAuthStatus.Ok && await LoginByCookiesAsync())
+ return result;
+ throw new AuthenticationException("Ошибка авторизации по паролю");
}
- ///