Полностью переписанное api
All checks were successful
Release / pack-and-publish (release) Successful in 36s
All checks were successful
Release / pack-and-publish (release) Successful in 36s
This commit is contained in:
@@ -1,26 +1,19 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Account;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Account;
|
||||
|
||||
[YPassportRequest(WebRequestMethods.Http.Post, "registration-validations/auth/multi_step/commit_password")]
|
||||
internal class YGetAuthAppPasswordBuilder : YRequestBuilder<YAuthBase, string>
|
||||
public class YGetAuthAppPasswordBuilder : YAuthRequestBuilder<YAuthBase?, string>
|
||||
{
|
||||
public YGetAuthAppPasswordBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
protected override HttpContent GetContent(string tuple)
|
||||
{
|
||||
return new FormUrlEncodedContent(new Dictionary<string, string> {
|
||||
{ "csrf_token", storage.AuthToken.CsfrToken },
|
||||
{ "track_id", storage.AuthToken.TrackId },
|
||||
{ "password", tuple },
|
||||
public YGetAuthAppPasswordBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Post;
|
||||
protected override string PathTemplate => "registration-validations/auth/multi_step/commit_password";
|
||||
protected override HttpContent? GetContent(string password)
|
||||
=> new FormUrlEncodedContent(new Dictionary<string, string>
|
||||
{
|
||||
{ "csrf_token", Api.Storage.AuthToken.CsfrToken },
|
||||
{ "track_id", Api.Storage.AuthToken.TrackId },
|
||||
{ "password", password },
|
||||
{ "retpath", "https://passport.yandex.ru/am/finish?status=ok&from=Login" }
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,13 @@
|
||||
using System.Net;
|
||||
using System.Net.Http.Headers;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
using YandexMusic.API.Models.Account;
|
||||
|
||||
namespace YandexMusic.API.Requests.Account;
|
||||
|
||||
[YPassportRequest(WebRequestMethods.Http.Post, "registration-validations/textcaptcha")]
|
||||
internal class YGetAuthCaptchaBuilder : YRequestBuilder<Models.Account.YAuthCaptcha, string>
|
||||
public class YGetAuthCaptchaBuilder : YAuthRequestBuilder<YAuthCaptcha?, object>
|
||||
{
|
||||
public YGetAuthCaptchaBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
protected override HttpContent GetContent(string tuple)
|
||||
{
|
||||
return new FormUrlEncodedContent(new Dictionary<string, string> {
|
||||
{ "csrf_token", storage.AuthToken.CsfrToken },
|
||||
{ "track_id", storage.AuthToken.TrackId },
|
||||
});
|
||||
}
|
||||
|
||||
protected override void SetCustomHeaders(HttpRequestHeaders headers)
|
||||
{
|
||||
headers.Add("X-Requested-With", "XMLHttpRequest");
|
||||
}
|
||||
public YGetAuthCaptchaBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Post;
|
||||
protected override string PathTemplate => "registration-validations/textcaptcha";
|
||||
protected override HttpContent? GetContent(object _)
|
||||
=> new FormUrlEncodedContent(new Dictionary<string, string> { { "csrf_token", Api.Storage.AuthToken.CsfrToken }, { "track_id", Api.Storage.AuthToken.TrackId } });
|
||||
}
|
||||
@@ -1,36 +1,14 @@
|
||||
using System.Net;
|
||||
using System.Net.Http.Headers;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Account;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Account;
|
||||
|
||||
[YMobileProxyRequest(WebRequestMethods.Http.Post, "1/bundle/oauth/token_by_sessionid")]
|
||||
internal class YGetAuthCookiesBuilder : YRequestBuilder<YAccessToken, string>
|
||||
public class YGetAuthCookiesBuilder : YAuthRequestBuilder<YAccessToken?, object>
|
||||
{
|
||||
public YGetAuthCookiesBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void SetCustomHeaders(HttpRequestHeaders headers)
|
||||
{
|
||||
CookieCollection cookieCollection = new() {
|
||||
storage.Context.Cookies.GetCookies(new Uri("https://yandex.ru/")),
|
||||
storage.Context.Cookies.GetCookies(new Uri("https://passport.yandex.ru/"))
|
||||
};
|
||||
|
||||
headers.Add("Ya-Client-Cookie", string.Join(";", cookieCollection.Select(c => $"{c.Name}={c.Value}")));
|
||||
headers.Add("Ya-Client-Host", "passport.yandex.ru");
|
||||
}
|
||||
|
||||
protected override HttpContent GetContent(string tuple)
|
||||
{
|
||||
return new FormUrlEncodedContent(new Dictionary<string, string> {
|
||||
{ "client_id", YConstants.XClientId },
|
||||
{ "client_secret", YConstants.XClientSecret }
|
||||
});
|
||||
}
|
||||
public YGetAuthCookiesBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Post;
|
||||
protected override string PathTemplate => "1/bundle/oauth/token_by_sessionid";
|
||||
protected override HttpContent? GetContent(object _)
|
||||
=> new FormUrlEncodedContent(new Dictionary<string, string> { { "client_id", YConstants.XClientId }, { "client_secret", YConstants.XClientSecret } });
|
||||
}
|
||||
@@ -1,17 +1,11 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Account;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Account;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Get, "account/status")]
|
||||
public class YGetAuthInfoBuilder : YRequestBuilder<YResponse<YAccountResult>, object>
|
||||
public class YGetAuthInfoBuilder : YMusicRequestBuilder<YAccountResult?, object>
|
||||
{
|
||||
public YGetAuthInfoBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
public YGetAuthInfoBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "account/status";
|
||||
}
|
||||
@@ -1,29 +1,13 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
using YandexMusic.API.Models.Account;
|
||||
|
||||
namespace YandexMusic.API.Requests.Account;
|
||||
|
||||
[YPassportRequest(WebRequestMethods.Http.Post, "registration-validations/auth/send_magic_letter")]
|
||||
internal class YGetAuthLetterBuilder : YRequestBuilder<Models.Account.YAuthLetter, string>
|
||||
public class YGetAuthLetterBuilder : YAuthRequestBuilder<YAuthLetter?, object>
|
||||
{
|
||||
public YGetAuthLetterBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
protected override HttpContent GetContent(string tuple)
|
||||
{
|
||||
if (storage.AuthToken == null)
|
||||
{
|
||||
throw new Exception("Не найдена сессия входа.");
|
||||
}
|
||||
|
||||
return new FormUrlEncodedContent(new Dictionary<string, string>
|
||||
{
|
||||
{ "csrf_token", storage.AuthToken.CsfrToken },
|
||||
{ "track_id", storage.AuthToken.TrackId },
|
||||
});
|
||||
}
|
||||
public YGetAuthLetterBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Post;
|
||||
protected override string PathTemplate => "registration-validations/auth/send_magic_letter";
|
||||
protected override HttpContent? GetContent(object _)
|
||||
=> new FormUrlEncodedContent(new Dictionary<string, string> { { "csrf_token", Api.Storage.AuthToken.CsfrToken }, { "track_id", Api.Storage.AuthToken.TrackId } });
|
||||
}
|
||||
@@ -1,31 +1,13 @@
|
||||
using System.Net;
|
||||
using System.Net.Http.Headers;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Account;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Account;
|
||||
|
||||
[YPassportRequest(WebRequestMethods.Http.Post, "registration-validations/checkHuman")]
|
||||
internal class YGetAuthLoginCaptchaBuilder : YRequestBuilder<YAuthBase, string>
|
||||
public class YGetAuthLoginCaptchaBuilder : YAuthRequestBuilder<YAuthBase?, string>
|
||||
{
|
||||
public YGetAuthLoginCaptchaBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
protected override HttpContent GetContent(string tuple)
|
||||
{
|
||||
return new FormUrlEncodedContent(new Dictionary<string, string> {
|
||||
{ "csrf_token", storage.AuthToken.CsfrToken },
|
||||
{ "track_id", storage.AuthToken.TrackId },
|
||||
{ "answer", tuple }
|
||||
});
|
||||
}
|
||||
|
||||
protected override void SetCustomHeaders(HttpRequestHeaders headers)
|
||||
{
|
||||
headers.Add("X-Requested-With", "XMLHttpRequest");
|
||||
}
|
||||
public YGetAuthLoginCaptchaBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Post;
|
||||
protected override string PathTemplate => "registration-validations/checkHuman";
|
||||
protected override HttpContent? GetContent(string captchaAnswer)
|
||||
=> new FormUrlEncodedContent(new Dictionary<string, string> { { "csrf_token", Api.Storage.AuthToken.CsfrToken }, { "track_id", Api.Storage.AuthToken.TrackId }, { "answer", captchaAnswer } });
|
||||
}
|
||||
@@ -1,24 +1,13 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Account;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Account;
|
||||
|
||||
[YPassportRequest(WebRequestMethods.Http.Post, "auth/letter/status/")]
|
||||
internal class YGetAuthLoginLetterBuilder : YRequestBuilder<YAuthLetterStatus, string>
|
||||
public class YGetAuthLoginLetterBuilder : YAuthRequestBuilder<YAuthLetterStatus?, object>
|
||||
{
|
||||
public YGetAuthLoginLetterBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
protected override HttpContent GetContent(string tuple)
|
||||
{
|
||||
return new FormUrlEncodedContent(new Dictionary<string, string> {
|
||||
{ "csrf_token", storage.AuthToken.CsfrToken },
|
||||
{ "track_id", storage.AuthToken.TrackId },
|
||||
});
|
||||
}
|
||||
public YGetAuthLoginLetterBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Post;
|
||||
protected override string PathTemplate => "auth/letter/status/";
|
||||
protected override HttpContent? GetContent(object _)
|
||||
=> new FormUrlEncodedContent(new Dictionary<string, string> { { "csrf_token", Api.Storage.AuthToken.CsfrToken }, { "track_id", Api.Storage.AuthToken.TrackId } });
|
||||
}
|
||||
@@ -1,24 +1,23 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Account;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Account;
|
||||
|
||||
[YPassportRequest(WebRequestMethods.Http.Post, "auth/new/magic/status/")]
|
||||
internal class YGetAuthLoginQRBuilder : YRequestBuilder<YAuthQRStatus, string>
|
||||
internal class YGetAuthLoginQRBuilder : YAuthRequestBuilder<YAuthQRStatus, string>
|
||||
{
|
||||
public YGetAuthLoginQRBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
public YGetAuthLoginQRBuilder(YandexMusicApi yandex) : base(yandex)
|
||||
{
|
||||
}
|
||||
|
||||
protected override string Method => WebRequestMethods.Http.Post;
|
||||
|
||||
protected override string PathTemplate => "auth/new/magic/status/";
|
||||
|
||||
protected override HttpContent GetContent(string tuple)
|
||||
{
|
||||
return new FormUrlEncodedContent(new Dictionary<string, string> {
|
||||
{ "csrf_token", storage.AuthToken.CsfrToken },
|
||||
{ "track_id", storage.AuthToken.TrackId }
|
||||
{ "csrf_token", Api.Storage.AuthToken.CsfrToken },
|
||||
{ "track_id", Api.Storage.AuthToken.TrackId }
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,13 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Account;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Account;
|
||||
|
||||
[YPassportRequest(WebRequestMethods.Http.Post, "registration-validations/auth/multi_step/start")]
|
||||
internal class YGetAuthLoginUserBuilder : YRequestBuilder<YAuthTypes, (string token, string login)>
|
||||
public class YGetAuthLoginUserBuilder : YAuthRequestBuilder<YAuthTypes?, (string token, string login)>
|
||||
{
|
||||
public YGetAuthLoginUserBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
protected override HttpContent GetContent((string token, string login) tuple)
|
||||
{
|
||||
return new FormUrlEncodedContent(new Dictionary<string, string> {
|
||||
{ "csrf_token", tuple.token },
|
||||
{ "login", tuple.login }
|
||||
});
|
||||
}
|
||||
public YGetAuthLoginUserBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Post;
|
||||
protected override string PathTemplate => "registration-validations/auth/multi_step/start";
|
||||
protected override HttpContent? GetContent((string token, string login) tuple)
|
||||
=> new FormUrlEncodedContent(new Dictionary<string, string> { { "csrf_token", tuple.token }, { "login", tuple.login } });
|
||||
}
|
||||
@@ -1,23 +1,13 @@
|
||||
using System.Collections.Specialized;
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using System.Net;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Account;
|
||||
|
||||
[YPassportRequest(WebRequestMethods.Http.Get, "am")]
|
||||
internal class YGetAuthMethodsBuilder : YRequestBuilder<HttpResponseMessage, string>
|
||||
public class YGetAuthMethodsBuilder : YRequestBuilder<object>
|
||||
{
|
||||
public YGetAuthMethodsBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
public YGetAuthMethodsBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "am";
|
||||
|
||||
protected override NameValueCollection GetQueryParams(string tuple)
|
||||
{
|
||||
return new NameValueCollection {
|
||||
{ "app_platform", "android" }
|
||||
};
|
||||
}
|
||||
protected override string BaseUrl => YConstants.Endpoints.PassportUrl;
|
||||
}
|
||||
@@ -1,25 +1,19 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using System.Net.Http.Headers;
|
||||
using YandexMusic.API.Models.Account;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Account;
|
||||
|
||||
[YPassportRequest(WebRequestMethods.Http.Post, "registration-validations/auth/password/submit")]
|
||||
internal class YGetAuthQRBuilder : YRequestBuilder<YAuthQR, string>
|
||||
public class YGetAuthQRBuilder : YAuthRequestBuilder<YAuthQR?, object>
|
||||
{
|
||||
public YGetAuthQRBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
public YGetAuthQRBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Post;
|
||||
protected override string PathTemplate => "pwl-yandex/api/passport/auth/password/submit";
|
||||
protected override HttpContent? GetContent(object _)
|
||||
=> new FormUrlEncodedContent(new Dictionary<string, string> { { "retpath", "" } });
|
||||
protected override void SetCustomHeaders(HttpRequestHeaders headers)
|
||||
{
|
||||
}
|
||||
|
||||
protected override HttpContent GetContent(string tuple)
|
||||
{
|
||||
return new FormUrlEncodedContent(new Dictionary<string, string> {
|
||||
{ "csrf_token", storage.AuthToken.CsfrToken },
|
||||
{ "retpath", "https://passport.yandex.ru/profile" },
|
||||
{ "with_code", "1" },
|
||||
});
|
||||
headers.Add("X-Csrf-Token", Api.Storage.AuthToken.CsfrToken);
|
||||
headers.Add("Process-Uuid", Api.Storage.AuthToken.ProcessUuid);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,12 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Account;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Account;
|
||||
|
||||
[YLoginRequest(WebRequestMethods.Http.Get, "info")]
|
||||
public class YGetLoginInfoBuilder : YRequestBuilder<YLoginInfo, object>
|
||||
public class YGetLoginInfoBuilder : YAuthRequestBuilder<YLoginInfo?, object>
|
||||
{
|
||||
public YGetLoginInfoBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
public YGetLoginInfoBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "info";
|
||||
}
|
||||
@@ -1,35 +1,25 @@
|
||||
using System.Net;
|
||||
using System.Net.Http.Headers;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Account;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Account;
|
||||
|
||||
[YOAuthMobile(WebRequestMethods.Http.Post, "/1/token")]
|
||||
internal class YGetMusicTokenBuilder : YRequestBuilder<YAccessToken, string>
|
||||
public class YGetMusicTokenBuilder : YAuthRequestBuilder<YAccessToken?, object>
|
||||
{
|
||||
public YGetMusicTokenBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
protected override HttpContent GetContent(string tuple)
|
||||
{
|
||||
return new FormUrlEncodedContent(new Dictionary<string, string>
|
||||
public YGetMusicTokenBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Post;
|
||||
protected override string PathTemplate => "/1/token";
|
||||
protected override HttpContent? GetContent(object _)
|
||||
=> new FormUrlEncodedContent(new Dictionary<string, string>
|
||||
{
|
||||
{ "client_id", YConstants.ClientId },
|
||||
{ "client_secret", YConstants.ClientSecret },
|
||||
{ "grant_type", "x-token" },
|
||||
{ "access_token", storage.AccessToken.AccessToken }
|
||||
{ "access_token", Api.Storage.AccessToken.AccessToken }
|
||||
});
|
||||
}
|
||||
|
||||
protected override void SetCustomHeaders(HttpRequestHeaders headers)
|
||||
{
|
||||
headers.Remove("Authorization");
|
||||
|
||||
base.SetCustomHeaders(headers);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +1,19 @@
|
||||
using System.Collections.Specialized;
|
||||
using System.Net;
|
||||
using System.Net.Http.Headers;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Account;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Account;
|
||||
|
||||
[YMobileProxyRequest(WebRequestMethods.Http.Get, "/1/bundle/account/short_info/")]
|
||||
internal class YGetShortAccountInifoBuilder : YRequestBuilder<YShortAccountInfo, object>
|
||||
public class YGetShortAccountInfoBuilder : YAuthRequestBuilder<YShortAccountInfo?, object>
|
||||
{
|
||||
public YGetShortAccountInifoBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
protected override NameValueCollection GetQueryParams(object tuple)
|
||||
{
|
||||
return new NameValueCollection {
|
||||
{ "avatar_size", "islands-300" }
|
||||
};
|
||||
}
|
||||
|
||||
public YGetShortAccountInfoBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "1/bundle/account/short_info/";
|
||||
protected override NameValueCollection GetQueryParams(object _)
|
||||
=> new() { { "avatar_size", "islands-300" } };
|
||||
protected override void SetCustomHeaders(HttpRequestHeaders headers)
|
||||
{
|
||||
headers.Add("Ya-Consumer-Authorization", $"OAuth {storage.AccessToken.AccessToken}");
|
||||
headers.Add("Ya-Consumer-Authorization", $"OAuth {Api.Storage.AccessToken.AccessToken}");
|
||||
}
|
||||
}
|
||||
19
YandexMusic.API/Requests/Account/YPostAuthStats.cs
Normal file
19
YandexMusic.API/Requests/Account/YPostAuthStats.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using System.Net;
|
||||
using System.Net.Http.Headers;
|
||||
using YandexMusic.API.Models.Account;
|
||||
|
||||
namespace YandexMusic.API.Requests.Account;
|
||||
|
||||
public class YPostAuthStats : YAuthRequestBuilder<YAuthEmpty?, object>
|
||||
{
|
||||
public YPostAuthStats(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Post;
|
||||
protected override string PathTemplate => "pwl-yandex/api/passport/stats";
|
||||
protected override HttpContent? GetContent(object _)
|
||||
=> new FormUrlEncodedContent(new Dictionary<string, string> { { "messageType", "CLIENT_READY" } });
|
||||
protected override void SetCustomHeaders(HttpRequestHeaders headers)
|
||||
{
|
||||
headers.Add("X-Csrf-Token", Api.Storage.AuthToken.CsfrToken);
|
||||
headers.Add("Process-Uuid", Api.Storage.AuthToken.ProcessUuid);
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,13 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Album;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Album;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Get, "albums/{albumId}/with-tracks")]
|
||||
public class YGetAlbumBuilder : YRequestBuilder<YResponse<YAlbum>, string>
|
||||
public class YGetAlbumBuilder : YMusicRequestBuilder<YAlbum?, string>
|
||||
{
|
||||
public YGetAlbumBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
public YGetAlbumBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "albums/{albumId}/with-tracks";
|
||||
protected override Dictionary<string, string> GetSubstitutions(string albumId)
|
||||
{
|
||||
return new Dictionary<string, string> {
|
||||
{ "albumId", albumId }
|
||||
};
|
||||
}
|
||||
=> new() { { "albumId", albumId } };
|
||||
}
|
||||
@@ -1,24 +1,13 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Album;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Album;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Post, "albums")]
|
||||
public class YGetAlbumsBuilder : YRequestBuilder<YResponse<List<YAlbum>>, IEnumerable<string>>
|
||||
public class YGetAlbumsBuilder : YMusicRequestBuilder<List<YAlbum>?, IEnumerable<string>>
|
||||
{
|
||||
public YGetAlbumsBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
protected override HttpContent GetContent(IEnumerable<string> albumIds)
|
||||
{
|
||||
return new FormUrlEncodedContent(new Dictionary<string, string> {
|
||||
{ "album-ids", string.Join(",", albumIds) }
|
||||
});
|
||||
}
|
||||
public YGetAlbumsBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Post;
|
||||
protected override string PathTemplate => "albums";
|
||||
protected override HttpContent? GetContent(IEnumerable<string> albumIds)
|
||||
=> new FormUrlEncodedContent(new Dictionary<string, string> { { "album-ids", string.Join(",", albumIds) } });
|
||||
}
|
||||
@@ -1,24 +1,13 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Artist;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Artist;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Get, "artists/{artistId}/brief-info")]
|
||||
public class YGetArtistBuilder : YRequestBuilder<YResponse<YArtistBriefInfo>, string>
|
||||
public class YGetArtistBuilder : YMusicRequestBuilder<YArtistBriefInfo?, string>
|
||||
{
|
||||
public YGetArtistBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
public YGetArtistBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "artists/{artistId}/brief-info";
|
||||
protected override Dictionary<string, string> GetSubstitutions(string artistId)
|
||||
{
|
||||
return new Dictionary<string, string> {
|
||||
{ "artistId", artistId }
|
||||
};
|
||||
}
|
||||
=> new() { { "artistId", artistId } };
|
||||
}
|
||||
@@ -1,31 +1,16 @@
|
||||
using System.Collections.Specialized;
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Artist;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Artist;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Get, "artists/{artistId}/tracks")]
|
||||
public class YGetArtistTrackBuilder : YRequestBuilder<YResponse<YTracksPage>, (string id, int page, int pageSize)>
|
||||
public class YGetArtistTrackBuilder : YMusicRequestBuilder<YTracksPage?, (string id, int page, int pageSize)>
|
||||
{
|
||||
public YGetArtistTrackBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth) { }
|
||||
|
||||
public YGetArtistTrackBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "artists/{artistId}/tracks";
|
||||
protected override Dictionary<string, string> GetSubstitutions((string id, int page, int pageSize) tuple)
|
||||
{
|
||||
return new Dictionary<string, string> {
|
||||
{ "artistId", tuple.id },
|
||||
};
|
||||
}
|
||||
|
||||
=> new() { { "artistId", tuple.id } };
|
||||
protected override NameValueCollection GetQueryParams((string id, int page, int pageSize) tuple)
|
||||
{
|
||||
return new NameValueCollection {
|
||||
{ "page", tuple.page.ToString() },
|
||||
{ "pageSize", tuple.pageSize.ToString() },
|
||||
};
|
||||
}
|
||||
=> new() { { "page", tuple.page.ToString() }, { "pageSize", tuple.pageSize.ToString() } };
|
||||
}
|
||||
@@ -1,24 +1,13 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Artist;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Artist;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Post, "artists")]
|
||||
public class YGetArtistsBuilder : YRequestBuilder<YResponse<List<YArtist>>, IEnumerable<string>>
|
||||
public class YGetArtistsBuilder : YMusicRequestBuilder<List<YArtist>?, IEnumerable<string>>
|
||||
{
|
||||
public YGetArtistsBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
protected override HttpContent GetContent(IEnumerable<string> artistIds)
|
||||
{
|
||||
return new FormUrlEncodedContent(new Dictionary<string, string> {
|
||||
{ "artist-Ids", string.Join(",", artistIds) }
|
||||
});
|
||||
}
|
||||
public YGetArtistsBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Post;
|
||||
protected override string PathTemplate => "artists";
|
||||
protected override HttpContent? GetContent(IEnumerable<string> artistIds)
|
||||
=> new FormUrlEncodedContent(new Dictionary<string, string> { { "artist-Ids", string.Join(",", artistIds) } });
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
public class YApiRequestAttribute : YBasePathRequestAttribute
|
||||
{
|
||||
public YApiRequestAttribute(string method, string url) : base(method, url)
|
||||
{
|
||||
basePath = "https://api.music.yandex.net";
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
namespace YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
/// <summary>
|
||||
/// Атрибут запроса относительно базового адреса
|
||||
/// </summary>
|
||||
public class YBasePathRequestAttribute : YRequestAttribute
|
||||
{
|
||||
#region Поля
|
||||
|
||||
protected string basePath;
|
||||
|
||||
#endregion Поля
|
||||
|
||||
#region Свойства
|
||||
public override string Url => GetFullUrl();
|
||||
|
||||
#endregion Свойства
|
||||
|
||||
#region Вспомогательные функции
|
||||
|
||||
private string GetFullUrl()
|
||||
{
|
||||
return $"{basePath.TrimEnd('/')}/{path.TrimStart('/')}";
|
||||
}
|
||||
|
||||
#endregion Вспомогательные функции
|
||||
|
||||
public YBasePathRequestAttribute(string method, string url) : base(method, url)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
public class YLoginRequestAttribute : YBasePathRequestAttribute
|
||||
{
|
||||
public YLoginRequestAttribute(string method, string url) : base(method, url)
|
||||
{
|
||||
basePath = "https://login.yandex.ru";
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
public class YMobileProxyRequestAttribute : YBasePathRequestAttribute
|
||||
{
|
||||
public YMobileProxyRequestAttribute(string method, string url) : base(method, url)
|
||||
{
|
||||
basePath = "https://mobileproxy.passport.yandex.net";
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
public class YOAuthMobileAttribute : YBasePathRequestAttribute
|
||||
{
|
||||
public YOAuthMobileAttribute(string method, string url) : base(method, url)
|
||||
{
|
||||
basePath = "https://oauth.mobile.yandex.net";
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
public class YOAuthRequestAttribute : YBasePathRequestAttribute
|
||||
{
|
||||
public YOAuthRequestAttribute(string method, string url) : base(method, url)
|
||||
{
|
||||
basePath = "https://oauth.yandex.ru";
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
public class YPassportRequestAttribute : YBasePathRequestAttribute
|
||||
{
|
||||
public YPassportRequestAttribute(string method, string url) : base(method, url)
|
||||
{
|
||||
basePath = "https://passport.yandex.ru";
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
namespace YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
/// <summary>
|
||||
/// Атрибут запроса без привязки к базовому адресу
|
||||
/// </summary>
|
||||
public class YRequestAttribute : Attribute
|
||||
{
|
||||
#region Поля
|
||||
|
||||
protected string path;
|
||||
|
||||
#endregion Поля
|
||||
|
||||
#region Свойства
|
||||
|
||||
public string Method { get; }
|
||||
public virtual string Url => path;
|
||||
|
||||
#endregion Свойства
|
||||
|
||||
public YRequestAttribute(string method, string url)
|
||||
{
|
||||
Method = method;
|
||||
path = url;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
public class YWebApiRequestAttribute : YBasePathRequestAttribute
|
||||
{
|
||||
public YWebApiRequestAttribute(string method, string url) : base(method, url)
|
||||
{
|
||||
basePath = "https://music.yandex.ru";
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
using System.Net;
|
||||
|
||||
namespace YandexMusic.API.Requests.Common;
|
||||
|
||||
public class HttpContext
|
||||
{
|
||||
public CookieContainer Cookies;
|
||||
|
||||
public HttpContext()
|
||||
{
|
||||
Cookies = new CookieContainer();
|
||||
}
|
||||
|
||||
public IWebProxy WebProxy { get; set; }
|
||||
|
||||
public long GetTimeInterval()
|
||||
{
|
||||
DateTime dt = TimeZoneInfo.ConvertTimeToUtc(DateTime.Now);
|
||||
DateTime dt1970 = new(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
|
||||
TimeSpan tsInterval = dt.Subtract(dt1970);
|
||||
long iMilliseconds = Convert.ToInt64(tsInterval.TotalMilliseconds);
|
||||
|
||||
return iMilliseconds;
|
||||
}
|
||||
}
|
||||
18
YandexMusic.API/Requests/Common/YAuthRequestBuilder.cs
Normal file
18
YandexMusic.API/Requests/Common/YAuthRequestBuilder.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System.Net.Http.Headers;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
|
||||
namespace YandexMusic.API.Requests;
|
||||
|
||||
/// <summary>Базовый класс для запросов к Passport (passport.yandex.ru).</summary>
|
||||
public abstract class YAuthRequestBuilder<TResponse, TParams> : YJsonRequestBuilder<TResponse, TParams>
|
||||
{
|
||||
protected override string BaseUrl => YConstants.Endpoints.PassportUrl;
|
||||
|
||||
protected YAuthRequestBuilder(YandexMusicApi api) : base(api) { }
|
||||
|
||||
protected override void SetCustomHeaders(HttpRequestHeaders headers)
|
||||
{
|
||||
base.SetCustomHeaders(headers);
|
||||
headers.Add("X-Requested-With", "XMLHttpRequest");
|
||||
}
|
||||
}
|
||||
@@ -7,4 +7,10 @@ internal class YConstants
|
||||
|
||||
public const string XClientId = "c0ebe342af7d48fbbbfcf2d2eedb8f9e";
|
||||
public const string XClientSecret = "ad0a908f0aa341a182a37ecd75bc319e";
|
||||
|
||||
internal static class Endpoints
|
||||
{
|
||||
public const string MusicUrl = "https://api.music.yandex.net";
|
||||
public const string PassportUrl = "https://passport.yandex.ru/";
|
||||
}
|
||||
}
|
||||
54
YandexMusic.API/Requests/Common/YJsonRequestBuilder.cs
Normal file
54
YandexMusic.API/Requests/Common/YJsonRequestBuilder.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using YandexMusic.API.Converters;
|
||||
using YandexMusic.API.Models.Common;
|
||||
|
||||
namespace YandexMusic.API.Requests.Common;
|
||||
|
||||
/// <summary>
|
||||
/// Строитель запросов с десериализацией JSON-ответа в TResponse.
|
||||
/// </summary>
|
||||
public abstract class YJsonRequestBuilder<TResponse, TParams> : YRequestBuilder<TParams>
|
||||
{
|
||||
protected YJsonRequestBuilder(YandexMusicApi api) : base(api) { }
|
||||
|
||||
protected virtual async Task<TResponse?> DeserializeAsync(HttpResponseMessage response)
|
||||
{
|
||||
var json = await response.Content.ReadAsStringAsync();
|
||||
|
||||
var options = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNameCaseInsensitive = true,
|
||||
Converters = {
|
||||
new JsonStringEnumConverter(JsonNamingPolicy.KebabCaseLower),
|
||||
new IntToStringConverter(),
|
||||
new StringToIntConverter(),
|
||||
new YExecutionContextConverter(Api, Storage),
|
||||
}
|
||||
};
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
var error = JsonSerializer.Deserialize<YErrorResponse>(json, options);
|
||||
throw error ?? new Exception($"Ошибка HTTP {response.StatusCode}: {json}");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return JsonSerializer.Deserialize<TResponse>(json, options);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception($"Ошибка десериализации: {ex.Message}\nJSON: {json}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Выполняет запрос и возвращает десериализованный объект типа TResponse.
|
||||
/// </summary>
|
||||
public async Task<TResponse?> ExecuteAsync(TParams parameters)
|
||||
{
|
||||
using var response = await ExecuteRawAsync(parameters);
|
||||
return await DeserializeAsync(response);
|
||||
}
|
||||
}
|
||||
55
YandexMusic.API/Requests/Common/YMusicRequestBuilder.cs
Normal file
55
YandexMusic.API/Requests/Common/YMusicRequestBuilder.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using YandexMusic.API.Converters;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
|
||||
namespace YandexMusic.API.Requests;
|
||||
|
||||
/// <summary>Базовый класс для запросов к API Яндекс Музыки (api.music.yandex.net).</summary>
|
||||
public abstract class YMusicRequestBuilder<TResponse, TParams> : YJsonRequestBuilder<TResponse, TParams>
|
||||
{
|
||||
protected override string BaseUrl => YConstants.Endpoints.MusicUrl;
|
||||
|
||||
protected YMusicRequestBuilder(YandexMusicApi api) : base(api) { }
|
||||
|
||||
protected override void SetCustomHeaders(HttpRequestHeaders headers)
|
||||
{
|
||||
base.SetCustomHeaders(headers);
|
||||
headers.Add("X-Yandex-Music-Client", Storage.DeviceId);
|
||||
}
|
||||
|
||||
protected override async Task<TResponse?> DeserializeAsync(HttpResponseMessage response)
|
||||
{
|
||||
var json = await response.Content.ReadAsStringAsync();
|
||||
|
||||
var options = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNameCaseInsensitive = true,
|
||||
Converters = {
|
||||
new JsonStringEnumConverter(JsonNamingPolicy.KebabCaseLower),
|
||||
new IntToStringConverter(),
|
||||
new StringToIntConverter(),
|
||||
new YExecutionContextConverter(Api, Storage),
|
||||
}
|
||||
};
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
var error = JsonSerializer.Deserialize<YErrorResponse>(json, options);
|
||||
throw error ?? new Exception($"Ошибка HTTP {response.StatusCode}: {json}");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var uResponse = JsonSerializer.Deserialize<YResponse<TResponse>>(json, options);
|
||||
if (uResponse == null) return default;
|
||||
return uResponse.Result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception($"Ошибка десериализации: {ex.Message}\nJSON: {json}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Common.Providers;
|
||||
|
||||
namespace YandexMusic.API.Requests.Common;
|
||||
|
||||
internal class YRequest<T>
|
||||
{
|
||||
private HttpRequestMessage msg;
|
||||
private IRequestProvider provider;
|
||||
|
||||
protected YandexMusicApi api;
|
||||
|
||||
public YRequest(HttpRequestMessage message, YandexMusicApi yandex, AuthStorage auth)
|
||||
{
|
||||
msg = message;
|
||||
api = yandex;
|
||||
provider = auth.Provider;
|
||||
}
|
||||
|
||||
public async Task<T> GetResponseAsync()
|
||||
{
|
||||
if (msg == null)
|
||||
return default;
|
||||
|
||||
HttpResponseMessage response = await provider.GetWebResponseAsync(msg);
|
||||
|
||||
if (typeof(T) == typeof(HttpResponseMessage))
|
||||
return (T)(object)response;
|
||||
|
||||
try
|
||||
{
|
||||
return await provider.GetDataFromResponseAsync<T>(api, response);
|
||||
}
|
||||
finally
|
||||
{
|
||||
response.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,38 +1,39 @@
|
||||
using System.Collections.Specialized;
|
||||
using System.Net;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web;
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Extensions;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Common;
|
||||
|
||||
/// <summary>Базовый строитель HTTP-запросов к API Яндекс.Музыки.</summary>
|
||||
/// <typeparam name="TResponse">Тип ответа.</typeparam>
|
||||
/// <summary>Базовый строитель HTTP-запросов.</summary>
|
||||
/// <typeparam name="TParams">Тип параметров запроса.</typeparam>
|
||||
public abstract class YRequestBuilder<TResponse, TParams>
|
||||
public abstract class YRequestBuilder<TParams>
|
||||
{
|
||||
private readonly YRequestAttribute _requestInfo;
|
||||
private Dictionary<string, string> _substitutions = null!;
|
||||
/// <summary>HTTP-метод (GET, POST и т.д.).</summary>
|
||||
protected abstract string Method { get; }
|
||||
|
||||
/// <summary>Базовый URL (например, "https://api.music.yandex.net").</summary>
|
||||
protected abstract string BaseUrl { get; }
|
||||
|
||||
/// <summary>Шаблон пути (может содержать плейсхолдеры вида {id}).</summary>
|
||||
protected abstract string PathTemplate { get; }
|
||||
|
||||
private readonly JsonSerializerOptions _jsonOptions;
|
||||
|
||||
protected readonly YandexMusicApi api;
|
||||
protected readonly AuthStorage storage;
|
||||
protected string device;
|
||||
/// <summary>Основной экземпляр API.</summary>
|
||||
protected YandexMusicApi Api { get; }
|
||||
|
||||
protected YRequestBuilder(YandexMusicApi yandex, AuthStorage auth)
|
||||
/// <summary>Хранилище авторизации (сокращение для Api.Storage).</summary>
|
||||
protected AuthStorage Storage => Api.Storage;
|
||||
|
||||
protected YRequestBuilder(YandexMusicApi api)
|
||||
{
|
||||
_requestInfo = GetType().GetCustomAttribute<YRequestAttribute>()
|
||||
?? throw new NotImplementedException($"Отсутствует атрибут {nameof(YRequestAttribute)}");
|
||||
api = yandex;
|
||||
storage = auth;
|
||||
device = $"os=CSharp; os_version=; manufacturer=FrigaT; model=Yandex Music API; clid=; device_id={storage.DeviceId}; uuid=random";
|
||||
|
||||
Api = api;
|
||||
_jsonOptions = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
@@ -41,57 +42,91 @@ public abstract class YRequestBuilder<TResponse, TParams>
|
||||
};
|
||||
}
|
||||
|
||||
private Uri BuildUri(TParams tuple)
|
||||
private string FullUrl => $"{BaseUrl.TrimEnd('/')}/{PathTemplate.TrimStart('/')}";
|
||||
|
||||
private Uri BuildUri(TParams parameters, Dictionary<string, string> substitutions)
|
||||
{
|
||||
var queryParams = GetQueryParams(tuple);
|
||||
var queryParams = GetQueryParams(parameters);
|
||||
var modifiedParams = HttpUtility.ParseQueryString(string.Empty);
|
||||
foreach (string? key in queryParams)
|
||||
if (key != null)
|
||||
modifiedParams[key] = ReplaceSubs(queryParams[key]!);
|
||||
var endpoint = ReplaceSubs(_requestInfo.Url);
|
||||
modifiedParams[key] = ReplaceSubs(queryParams[key]!, substitutions);
|
||||
var endpoint = ReplaceSubs(FullUrl, substitutions);
|
||||
var builder = new UriBuilder(endpoint) { Query = modifiedParams.ToString() ?? string.Empty };
|
||||
return builder.Uri;
|
||||
}
|
||||
|
||||
private HttpRequestMessage CreateMessage(TParams tuple)
|
||||
private HttpRequestMessage CreateMessage(TParams parameters, Dictionary<string, string> substitutions)
|
||||
{
|
||||
var msg = new HttpRequestMessage
|
||||
{
|
||||
RequestUri = BuildUri(tuple),
|
||||
Method = new HttpMethod(_requestInfo.Method),
|
||||
Content = GetContent(tuple)
|
||||
RequestUri = BuildUri(parameters, substitutions),
|
||||
Method = new HttpMethod(Method),
|
||||
Content = GetContent(parameters)
|
||||
};
|
||||
msg.Headers.TryAddWithoutValidation(HttpRequestHeader.AcceptCharset.GetName(), Encoding.UTF8.WebName);
|
||||
msg.Headers.TryAddWithoutValidation(HttpRequestHeader.AcceptEncoding.GetName(), "gzip");
|
||||
if (!string.IsNullOrEmpty(storage.Token))
|
||||
msg.Headers.TryAddWithoutValidation(HttpRequestHeader.Authorization.GetName(), $"OAuth {storage.Token}");
|
||||
msg.Headers.TryAddWithoutValidation(GetHeaderName(HttpRequestHeader.AcceptCharset), Encoding.UTF8.WebName);
|
||||
msg.Headers.TryAddWithoutValidation(GetHeaderName(HttpRequestHeader.AcceptEncoding), "gzip");
|
||||
if (!string.IsNullOrEmpty(Storage.Token))
|
||||
msg.Headers.TryAddWithoutValidation(GetHeaderName(HttpRequestHeader.Authorization), $"OAuth {Storage.Token}");
|
||||
SetCustomHeaders(msg.Headers);
|
||||
return msg;
|
||||
}
|
||||
|
||||
protected string ReplaceSubs(string str)
|
||||
// Вспомогательный метод: преобразование HttpRequestHeader в строку (как было в HttpRequestHeaderExtensions)
|
||||
private static string GetHeaderName(HttpRequestHeader header)
|
||||
{
|
||||
var subs = str.GetMatches(@"\{.+?\}");
|
||||
return SplitByCapitalLetter(header.ToString(), "-");
|
||||
}
|
||||
|
||||
// Вспомогательный метод: разбиение строки по заглавным буквам (из StringExtensions)
|
||||
private static string SplitByCapitalLetter(string str, string delimiter)
|
||||
{
|
||||
var matches = Regex.Matches(str, @"([A-Z]+)(?=([A-Z][a-z]|$)) | [A-Z][a-z].+?(?=([A-Z]|$))", RegexOptions.IgnorePatternWhitespace);
|
||||
return string.Join(delimiter, matches.Cast<Match>().Select(m => m.Value));
|
||||
}
|
||||
|
||||
// Вспомогательный метод: замена всех вхождений регулярного выражения (из StringExtensions)
|
||||
private static string ReplaceRegex(string input, string pattern, string replacement, RegexOptions options = RegexOptions.IgnoreCase)
|
||||
{
|
||||
return string.IsNullOrEmpty(input) ? string.Empty : Regex.Replace(input, pattern, replacement, options);
|
||||
}
|
||||
|
||||
// Вспомогательный метод: получение совпадений по регулярному выражению (из StringExtensions)
|
||||
private static string[] GetMatches(string input, string pattern, RegexOptions options = RegexOptions.IgnoreCase)
|
||||
{
|
||||
if (string.IsNullOrEmpty(input) || !Regex.IsMatch(input, pattern, options))
|
||||
return Array.Empty<string>();
|
||||
return Regex.Matches(input, pattern, options)
|
||||
.Cast<Match>()
|
||||
.Select(m => m.Value)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
private string ReplaceSubs(string str, Dictionary<string, string> substitutions)
|
||||
{
|
||||
var subs = GetMatches(str, @"\{.+?\}");
|
||||
foreach (var s in subs)
|
||||
{
|
||||
var key = s.ReplaceRegex(@"[\{\}]", string.Empty);
|
||||
if (!_substitutions.TryGetValue(key, out var value))
|
||||
var key = ReplaceRegex(s, @"[\{\}]", string.Empty);
|
||||
if (!substitutions.TryGetValue(key, out var value))
|
||||
throw new Exception($"Не найдена подстановка {s}");
|
||||
str = str.Replace(s, value);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
protected virtual Dictionary<string, string> GetSubstitutions(TParams tuple) => [];
|
||||
protected virtual NameValueCollection GetQueryParams(TParams tuple) => [];
|
||||
protected virtual HttpContent? GetContent(TParams tuple) => null;
|
||||
protected virtual Dictionary<string, string> GetSubstitutions(TParams parameters) => [];
|
||||
protected virtual NameValueCollection GetQueryParams(TParams parameters) => [];
|
||||
protected virtual HttpContent? GetContent(TParams parameters) => null;
|
||||
protected virtual void SetCustomHeaders(HttpRequestHeaders headers) { }
|
||||
|
||||
protected string SerializeJson(object data) => JsonSerializer.Serialize(data, _jsonOptions);
|
||||
|
||||
internal YRequest<TResponse> Build(TParams tuple)
|
||||
/// <summary>Выполняет запрос и возвращает десериализованный ответ.</summary>
|
||||
public async Task<HttpResponseMessage?> ExecuteRawAsync(TParams parameters)
|
||||
{
|
||||
_substitutions = GetSubstitutions(tuple);
|
||||
var msg = CreateMessage(tuple);
|
||||
return new YRequest<TResponse>(msg, api, storage);
|
||||
var substitutions = GetSubstitutions(parameters);
|
||||
using var msg = CreateMessage(parameters, substitutions);
|
||||
return await Api.HttpClient.SendAsync(msg);
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,12 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Feed;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Feed;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Get, "feed")]
|
||||
public class YGetFeedBuilder : YRequestBuilder<YResponse<YFeed>, object>
|
||||
public class YGetFeedBuilder : YMusicRequestBuilder<YFeed?, object>
|
||||
{
|
||||
public YGetFeedBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
public YGetFeedBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "feed";
|
||||
}
|
||||
@@ -1,32 +1,17 @@
|
||||
using System.Collections.Specialized;
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Label;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Label;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Get, "labels/{labelId}/albums")]
|
||||
public class YGetLabelAlbumsBuilder : YRequestBuilder<YResponse<YLabelAlbums>, (YLabel label, int pageNumber)>
|
||||
public class YGetLabelAlbumsBuilder : YMusicRequestBuilder<YLabelAlbums?, (YLabel label, int pageNumber)>
|
||||
{
|
||||
public YGetLabelAlbumsBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
protected override NameValueCollection GetQueryParams((YLabel label, int pageNumber) tuple)
|
||||
{
|
||||
return new NameValueCollection {
|
||||
{ "page", tuple.pageNumber.ToString() }
|
||||
};
|
||||
}
|
||||
|
||||
public YGetLabelAlbumsBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "labels/{labelId}/albums";
|
||||
protected override Dictionary<string, string> GetSubstitutions((YLabel label, int pageNumber) tuple)
|
||||
{
|
||||
return new Dictionary<string, string> {
|
||||
{ "labelId", tuple.label.Id }
|
||||
};
|
||||
}
|
||||
}
|
||||
=> new() { { "labelId", tuple.label.Id } };
|
||||
protected override NameValueCollection GetQueryParams((YLabel label, int pageNumber) tuple)
|
||||
=> new() { { "page", tuple.pageNumber.ToString() } };
|
||||
}
|
||||
@@ -1,32 +1,17 @@
|
||||
using System.Collections.Specialized;
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Label;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Label;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Get, "labels/{labelId}/artists")]
|
||||
public class YGetLabelArtistsBuilder : YRequestBuilder<YResponse<YLabelArtists>, (YLabel label, int pageNumber)>
|
||||
public class YGetLabelArtistsBuilder : YMusicRequestBuilder<YLabelArtists?, (YLabel label, int pageNumber)>
|
||||
{
|
||||
public YGetLabelArtistsBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
protected override NameValueCollection GetQueryParams((YLabel label, int pageNumber) tuple)
|
||||
{
|
||||
return new NameValueCollection {
|
||||
{ "page", tuple.pageNumber.ToString() }
|
||||
};
|
||||
}
|
||||
|
||||
public YGetLabelArtistsBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "labels/{labelId}/artists";
|
||||
protected override Dictionary<string, string> GetSubstitutions((YLabel label, int pageNumber) tuple)
|
||||
{
|
||||
return new Dictionary<string, string> {
|
||||
{ "labelId", tuple.label.Id }
|
||||
};
|
||||
}
|
||||
}
|
||||
=> new() { { "labelId", tuple.label.Id } };
|
||||
protected override NameValueCollection GetQueryParams((YLabel label, int pageNumber) tuple)
|
||||
=> new() { { "page", tuple.pageNumber.ToString() } };
|
||||
}
|
||||
@@ -1,17 +1,12 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Landing;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Landing;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Get, "children-landing/catalogue")]
|
||||
public class YGetChildrenLandingBuilder : YRequestBuilder<YResponse<YChildrenLanding>, object>
|
||||
public class YGetChildrenLandingBuilder : YMusicRequestBuilder<YChildrenLanding?, object>
|
||||
{
|
||||
public YGetChildrenLandingBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
public YGetChildrenLandingBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "children-landing/catalogue";
|
||||
}
|
||||
@@ -1,28 +1,17 @@
|
||||
using System.Collections.Specialized;
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Landing;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Landing;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Get, "landing3")]
|
||||
public class YGetLandingBuilder : YRequestBuilder<YResponse<YLanding>, YLandingBlockType[]>
|
||||
public class YGetLandingBuilder : YMusicRequestBuilder<YLanding?, YLandingBlockType[]>
|
||||
{
|
||||
public YGetLandingBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
public YGetLandingBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "landing3";
|
||||
protected override NameValueCollection GetQueryParams(YLandingBlockType[] blocks)
|
||||
{
|
||||
}
|
||||
|
||||
protected override NameValueCollection GetQueryParams(YLandingBlockType[] tuple)
|
||||
{
|
||||
string blocks = string.Join(",", tuple
|
||||
.Select(b => SerializeJson(b).Replace("\"", string.Empty)));
|
||||
|
||||
return new NameValueCollection {
|
||||
{ "blocks", blocks }
|
||||
};
|
||||
string blocksStr = string.Join(",", blocks.Select(b => SerializeJson(b).Replace("\"", "")));
|
||||
return new NameValueCollection { { "blocks", blocksStr } };
|
||||
}
|
||||
}
|
||||
@@ -1,36 +1,22 @@
|
||||
using System.Collections.Specialized;
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Landing.Entity.Entities.Context;
|
||||
using YandexMusic.API.Models.Library;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Library;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Get, "/users/{uid}/contexts")]
|
||||
public class YGetLibraryRecentlyListenedBuilder : YRequestBuilder<YResponse<YRecentlyListenedContext>,
|
||||
(IEnumerable<YPlayContextType> contextTypes, int trackCount, int contextCount)>
|
||||
public class YGetLibraryRecentlyListenedBuilder : YMusicRequestBuilder<YRecentlyListenedContext?, (IEnumerable<YPlayContextType> contextTypes, int trackCount, int contextCount)>
|
||||
{
|
||||
public YGetLibraryRecentlyListenedBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
public YGetLibraryRecentlyListenedBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "users/{uid}/contexts";
|
||||
protected override Dictionary<string, string> GetSubstitutions((IEnumerable<YPlayContextType> contextTypes, int trackCount, int contextCount) tuple)
|
||||
=> new() { { "uid", Api.Storage.User.Uid } };
|
||||
protected override NameValueCollection GetQueryParams((IEnumerable<YPlayContextType> contextTypes, int trackCount, int contextCount) tuple)
|
||||
{
|
||||
return new NameValueCollection {
|
||||
=> new()
|
||||
{
|
||||
{ "trackCount", tuple.trackCount.ToString() },
|
||||
{ "contextCount", tuple.contextCount.ToString() },
|
||||
{ "types", string.Join(",", tuple.contextTypes.Select(x => x.ToString().ToLowerInvariant())) }
|
||||
};
|
||||
}
|
||||
|
||||
protected override Dictionary<string, string> GetSubstitutions((IEnumerable<YPlayContextType> contextTypes, int trackCount, int contextCount) tuple)
|
||||
{
|
||||
return new Dictionary<string, string> {
|
||||
{ "uid", storage.User.Uid }
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,18 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Library;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Library;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Get, "users/{uid}/{type}/{section}")]
|
||||
public class YGetLibrarySectionBuilder<T> : YRequestBuilder<YResponse<T>, (YLibrarySection section, YLibrarySectionType type)>
|
||||
public class YGetLibrarySectionBuilder<T> : YMusicRequestBuilder<T?, (YLibrarySection section, YLibrarySectionType type)>
|
||||
{
|
||||
public YGetLibrarySectionBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
public YGetLibrarySectionBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "users/{uid}/{type}/{section}";
|
||||
protected override Dictionary<string, string> GetSubstitutions((YLibrarySection section, YLibrarySectionType type) tuple)
|
||||
{
|
||||
return new Dictionary<string, string> {
|
||||
{ "uid", storage.User.Uid },
|
||||
=> new()
|
||||
{
|
||||
{ "uid", Api.Storage.User.Uid },
|
||||
{ "type", tuple.type.ToString().ToLower() },
|
||||
{ "section", tuple.section.ToString().ToLower() },
|
||||
{ "section", tuple.section.ToString().ToLower() }
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,33 +1,20 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Library;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Library;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Post, "users/{uid}/{type}/{section}/add-multiple")]
|
||||
public class YLibraryAddBuilder<T> : YRequestBuilder<YResponse<T>, (string id, YLibrarySection section, YLibrarySectionType type)>
|
||||
public class YLibraryAddBuilder<T> : YMusicRequestBuilder<T?, (string id, YLibrarySection section, YLibrarySectionType type)>
|
||||
{
|
||||
public YLibraryAddBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
public YLibraryAddBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Post;
|
||||
protected override string PathTemplate => "users/{uid}/{type}/{section}/add-multiple";
|
||||
protected override Dictionary<string, string> GetSubstitutions((string id, YLibrarySection section, YLibrarySectionType type) tuple)
|
||||
{
|
||||
return new Dictionary<string, string> {
|
||||
{ "uid", storage.User.Uid },
|
||||
=> new()
|
||||
{
|
||||
{ "uid", Api.Storage.User.Uid },
|
||||
{ "type", tuple.type.ToString().ToLower() },
|
||||
{ "section", tuple.section.ToString().ToLower() },
|
||||
{ "section", tuple.section.ToString().ToLower() }
|
||||
};
|
||||
}
|
||||
|
||||
protected override HttpContent GetContent((string id, YLibrarySection section, YLibrarySectionType type) tuple)
|
||||
{
|
||||
return new FormUrlEncodedContent(new Dictionary<string, string> {
|
||||
{ $"{tuple.section.ToString().ToLower().TrimEnd('s')}-ids", tuple.id }
|
||||
});
|
||||
}
|
||||
protected override HttpContent? GetContent((string id, YLibrarySection section, YLibrarySectionType type) tuple)
|
||||
=> new FormUrlEncodedContent(new Dictionary<string, string> { { $"{tuple.section.ToString().ToLower().TrimEnd('s')}-ids", tuple.id } });
|
||||
}
|
||||
@@ -1,33 +1,20 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Library;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Library;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Post, "users/{uid}/{type}/{section}/remove")]
|
||||
public class YLibraryRemoveBuilder<T> : YRequestBuilder<YResponse<T>, (string id, YLibrarySection section, YLibrarySectionType type)>
|
||||
public class YLibraryRemoveBuilder<T> : YMusicRequestBuilder<T?, (string id, YLibrarySection section, YLibrarySectionType type)>
|
||||
{
|
||||
public YLibraryRemoveBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
public YLibraryRemoveBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Post;
|
||||
protected override string PathTemplate => "users/{uid}/{type}/{section}/remove";
|
||||
protected override Dictionary<string, string> GetSubstitutions((string id, YLibrarySection section, YLibrarySectionType type) tuple)
|
||||
{
|
||||
return new Dictionary<string, string> {
|
||||
{ "uid", storage.User.Uid },
|
||||
=> new()
|
||||
{
|
||||
{ "uid", Api.Storage.User.Uid },
|
||||
{ "type", tuple.type.ToString().ToLower() },
|
||||
{ "section", tuple.section.ToString().ToLower() },
|
||||
{ "section", tuple.section.ToString().ToLower() }
|
||||
};
|
||||
}
|
||||
|
||||
protected override HttpContent GetContent((string id, YLibrarySection section, YLibrarySectionType type) tuple)
|
||||
{
|
||||
return new FormUrlEncodedContent(new Dictionary<string, string> {
|
||||
{ $"{tuple.section.ToString().ToLower().TrimEnd('s')}-ids", tuple.id }
|
||||
});
|
||||
}
|
||||
protected override HttpContent? GetContent((string id, YLibrarySection section, YLibrarySectionType type) tuple)
|
||||
=> new FormUrlEncodedContent(new Dictionary<string, string> { { $"{tuple.section.ToString().ToLower().TrimEnd('s')}-ids", tuple.id } });
|
||||
}
|
||||
@@ -1,17 +1,12 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Pins;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Pins;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Get, "pins")]
|
||||
public class YGetPinsBuilder : YRequestBuilder<YResponse<YPins>, object>
|
||||
public class YGetPinsBuilder : YMusicRequestBuilder<YPins?, object>
|
||||
{
|
||||
public YGetPinsBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
public YGetPinsBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "pins";
|
||||
}
|
||||
@@ -1,25 +1,13 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Playlist;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Playlist;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Get, "users/{user}/playlists/{kind}")]
|
||||
public class YGetPlaylistBuilder : YRequestBuilder<YResponse<YPlaylist>, (string user, string kind)>
|
||||
public class YGetPlaylistBuilder : YMusicRequestBuilder<YPlaylist?, (string user, string kind)>
|
||||
{
|
||||
public YGetPlaylistBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
public YGetPlaylistBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "users/{user}/playlists/{kind}";
|
||||
protected override Dictionary<string, string> GetSubstitutions((string user, string kind) tuple)
|
||||
{
|
||||
return new Dictionary<string, string> {
|
||||
{ "user", tuple.user },
|
||||
{ "kind", tuple.kind },
|
||||
};
|
||||
}
|
||||
=> new() { { "user", tuple.user }, { "kind", tuple.kind } };
|
||||
}
|
||||
@@ -1,24 +1,13 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Playlist;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Playlist;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Get, "playlist/{uuid}")]
|
||||
public class YGetPlaylistByUuidBuilder : YRequestBuilder<YResponse<YPlaylist>, string>
|
||||
public class YGetPlaylistByUuidBuilder : YMusicRequestBuilder<YPlaylist?, string>
|
||||
{
|
||||
public YGetPlaylistByUuidBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
public YGetPlaylistByUuidBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "playlist/{uuid}";
|
||||
protected override Dictionary<string, string> GetSubstitutions(string uuid)
|
||||
{
|
||||
return new Dictionary<string, string> {
|
||||
{ "uuid", uuid },
|
||||
};
|
||||
}
|
||||
=> new() { { "uuid", uuid } };
|
||||
}
|
||||
@@ -1,24 +1,13 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Playlist;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Playlist;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Get, "users/{uid}/playlists/list")]
|
||||
public class YGetPlaylistFavoritesBuilder : YRequestBuilder<YResponse<List<YPlaylist>>, object>
|
||||
public class YGetPlaylistFavoritesBuilder : YMusicRequestBuilder<List<YPlaylist>?, object>
|
||||
{
|
||||
public YGetPlaylistFavoritesBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
protected override Dictionary<string, string> GetSubstitutions(object tuple)
|
||||
{
|
||||
return new Dictionary<string, string> {
|
||||
{ "uid", storage.User.Uid }
|
||||
};
|
||||
}
|
||||
public YGetPlaylistFavoritesBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "users/{uid}/playlists/list";
|
||||
protected override Dictionary<string, string> GetSubstitutions(object _)
|
||||
=> new() { { "uid", Api.Storage.User.Uid } };
|
||||
}
|
||||
@@ -1,24 +1,16 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Playlist;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Playlist;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Post, "playlists/list")]
|
||||
public class YGetPlaylistsBuilder : YRequestBuilder<YResponse<List<YPlaylist>>, IEnumerable<(string User, string Kind)>>
|
||||
public class YGetPlaylistsBuilder : YMusicRequestBuilder<List<YPlaylist>?, IEnumerable<(string User, string Kind)>>
|
||||
{
|
||||
public YGetPlaylistsBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
protected override HttpContent GetContent(IEnumerable<(string User, string Kind)> playlistIds)
|
||||
{
|
||||
return new FormUrlEncodedContent(new Dictionary<string, string> {
|
||||
public YGetPlaylistsBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Post;
|
||||
protected override string PathTemplate => "playlists/list";
|
||||
protected override HttpContent? GetContent(IEnumerable<(string User, string Kind)> playlistIds)
|
||||
=> new FormUrlEncodedContent(new Dictionary<string, string>
|
||||
{
|
||||
{ "playlist-Ids", string.Join(",", playlistIds.Select(t => $"{t.User}:{t.Kind}")) }
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,34 +1,20 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Playlist;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Playlist;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Post, "users/{uid}/playlists/{kind}/change")]
|
||||
public class YPlaylistChangeBuilder : YRequestBuilder<YResponse<YPlaylist>, (YPlaylist playlist, IEnumerable<YPlaylistChange> changes)>
|
||||
public class YPlaylistChangeBuilder : YMusicRequestBuilder<YPlaylist?, (YPlaylist playlist, IEnumerable<YPlaylistChange> changes)>
|
||||
{
|
||||
public YPlaylistChangeBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
public YPlaylistChangeBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Post;
|
||||
protected override string PathTemplate => "users/{uid}/playlists/{kind}/change";
|
||||
protected override Dictionary<string, string> GetSubstitutions((YPlaylist playlist, IEnumerable<YPlaylistChange> changes) tuple)
|
||||
{
|
||||
return new Dictionary<string, string> {
|
||||
{ "uid", storage.User.Uid },
|
||||
{ "kind", tuple.playlist.Kind }
|
||||
};
|
||||
}
|
||||
|
||||
protected override HttpContent GetContent((YPlaylist playlist, IEnumerable<YPlaylistChange> changes) tuple)
|
||||
{
|
||||
return new FormUrlEncodedContent(new Dictionary<string, string> {
|
||||
=> new() { { "uid", Api.Storage.User.Uid }, { "kind", tuple.playlist.Kind } };
|
||||
protected override HttpContent? GetContent((YPlaylist playlist, IEnumerable<YPlaylistChange> changes) tuple)
|
||||
=> new FormUrlEncodedContent(new Dictionary<string, string>
|
||||
{
|
||||
{ "kind", tuple.playlist.Kind },
|
||||
{ "revision", tuple.playlist.Revision.ToString() },
|
||||
{ "diff", SerializeJson(tuple.changes) }
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,32 +1,15 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Playlist;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Playlist;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Post, "users/{uid}/playlists/create")]
|
||||
public class YPlaylistCreateBuilder : YRequestBuilder<YResponse<YPlaylist>, string>
|
||||
public class YPlaylistCreateBuilder : YMusicRequestBuilder<YPlaylist?, string>
|
||||
{
|
||||
public YPlaylistCreateBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
public YPlaylistCreateBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Post;
|
||||
protected override string PathTemplate => "users/{uid}/playlists/create";
|
||||
protected override Dictionary<string, string> GetSubstitutions(string name)
|
||||
{
|
||||
return new Dictionary<string, string> {
|
||||
{ "uid", storage.User.Uid }
|
||||
};
|
||||
}
|
||||
|
||||
protected override HttpContent GetContent(string name)
|
||||
{
|
||||
return new FormUrlEncodedContent(new Dictionary<string, string> {
|
||||
{ "title", name },
|
||||
{ "visibility", "public" }
|
||||
});
|
||||
}
|
||||
=> new() { { "uid", Api.Storage.User.Uid } };
|
||||
protected override HttpContent? GetContent(string name)
|
||||
=> new FormUrlEncodedContent(new Dictionary<string, string> { { "title", name }, { "visibility", "public" } });
|
||||
}
|
||||
@@ -1,32 +1,12 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Playlist;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Playlist;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Post, "users/{uid}/playlists/{kind}/name")]
|
||||
public class YPlaylistRenameBuilder : YRequestBuilder<YResponse<YPlaylist>, (string kind, string name)>
|
||||
public class YPlaylistRemoveBuilder : YMusicRequestBuilder<HttpResponseMessage, string>
|
||||
{
|
||||
public YPlaylistRenameBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
protected override Dictionary<string, string> GetSubstitutions((string kind, string name) tuple)
|
||||
{
|
||||
return new Dictionary<string, string> {
|
||||
{ "uid", storage.User.Uid },
|
||||
{ "kind", tuple.kind }
|
||||
};
|
||||
}
|
||||
|
||||
protected override HttpContent GetContent((string kind, string name) tuple)
|
||||
{
|
||||
return new FormUrlEncodedContent(new Dictionary<string, string> {
|
||||
{ "value", tuple.name }
|
||||
});
|
||||
}
|
||||
public YPlaylistRemoveBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Post;
|
||||
protected override string PathTemplate => "users/{uid}/playlists/{kind}/delete";
|
||||
protected override Dictionary<string, string> GetSubstitutions(string kind)
|
||||
=> new() { { "uid", Api.Storage.User.Uid }, { "kind", kind } };
|
||||
}
|
||||
@@ -1,23 +1,15 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
using YandexMusic.API.Models.Playlist;
|
||||
|
||||
namespace YandexMusic.API.Requests.Playlist;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Post, "users/{uid}/playlists/{kind}/delete")]
|
||||
public class YPlaylistRemoveBuilder : YRequestBuilder<HttpResponseMessage, string>
|
||||
public class YPlaylistRenameBuilder : YMusicRequestBuilder<YPlaylist?, (string kind, string name)>
|
||||
{
|
||||
public YPlaylistRemoveBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
protected override Dictionary<string, string> GetSubstitutions(string kind)
|
||||
{
|
||||
return new Dictionary<string, string> {
|
||||
{ "uid", storage.User.Uid },
|
||||
{ "kind", kind }
|
||||
};
|
||||
}
|
||||
public YPlaylistRenameBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Post;
|
||||
protected override string PathTemplate => "users/{uid}/playlists/{kind}/name";
|
||||
protected override Dictionary<string, string> GetSubstitutions((string kind, string name) tuple)
|
||||
=> new() { { "uid", Api.Storage.User.Uid }, { "kind", tuple.kind } };
|
||||
protected override HttpContent? GetContent((string kind, string name) tuple)
|
||||
=> new FormUrlEncodedContent(new Dictionary<string, string> { { "value", tuple.name } });
|
||||
}
|
||||
@@ -1,24 +1,13 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Queue;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Queue;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Get, "queues/{queueId}")]
|
||||
public class YGetQueueBuilder : YRequestBuilder<YResponse<YQueue>, string>
|
||||
public class YGetQueueBuilder : YMusicRequestBuilder<YQueue?, string>
|
||||
{
|
||||
public YGetQueueBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
public YGetQueueBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "queues/{queueId}";
|
||||
protected override Dictionary<string, string> GetSubstitutions(string queueId)
|
||||
{
|
||||
return new Dictionary<string, string> {
|
||||
{ "queueId", queueId }
|
||||
};
|
||||
}
|
||||
}
|
||||
=> new() { { "queueId", queueId } };
|
||||
}
|
||||
@@ -4,40 +4,29 @@ using System.Net.Http.Json;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Queue;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Queue;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Post, "queues")]
|
||||
public class YQueueCreateBuilder : YRequestBuilder<YResponse<YNewQueue>, YQueue>
|
||||
public class YQueueCreateBuilder : YMusicRequestBuilder<YNewQueue?, YQueue>
|
||||
{
|
||||
public YQueueCreateBuilder(YandexMusicApi yandex, AuthStorage auth, string? device = null) : base(yandex, auth)
|
||||
private string? _device;
|
||||
public YQueueCreateBuilder(YandexMusicApi api, string? device = null) : base(api) => _device = device;
|
||||
protected override string Method => WebRequestMethods.Http.Post;
|
||||
protected override string PathTemplate => "queues";
|
||||
protected override HttpContent? GetContent(YQueue queue)
|
||||
{
|
||||
if (device != null)
|
||||
this.device = device;
|
||||
}
|
||||
|
||||
protected override HttpContent GetContent(YQueue queue)
|
||||
{
|
||||
JsonSerializerOptions settings = new()
|
||||
var options = new JsonSerializerOptions
|
||||
{
|
||||
Converters = {
|
||||
new JsonStringEnumConverter()
|
||||
},
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
||||
Converters = { new JsonStringEnumConverter() }
|
||||
};
|
||||
|
||||
return JsonContent.Create(queue, new MediaTypeHeaderValue("application/json"), settings);
|
||||
return JsonContent.Create(queue, new MediaTypeHeaderValue("application/json"), options);
|
||||
}
|
||||
|
||||
protected override void SetCustomHeaders(HttpRequestHeaders headers)
|
||||
{
|
||||
headers.Add("X-Yandex-Music-Device", device);
|
||||
if (!string.IsNullOrEmpty(_device))
|
||||
headers.Add("X-Yandex-Music-Device", _device);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,41 +1,27 @@
|
||||
using System.Collections.Specialized;
|
||||
using System.Net;
|
||||
using System.Net.Http.Headers;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Queue;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Queue;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Post, "queues/{queueId}/update-position")]
|
||||
public class YQueueUpdatePositionBuilder : YRequestBuilder<YResponse<YUpdatedQueue>, (string queueId, int currentIndex, bool isInteractive)>
|
||||
public class YQueueUpdatePositionBuilder : YMusicRequestBuilder<YUpdatedQueue?, (string queueId, int currentIndex, bool isInteractive)>
|
||||
{
|
||||
public YQueueUpdatePositionBuilder(YandexMusicApi yandex, AuthStorage auth, string device = null) : base(yandex, auth)
|
||||
{
|
||||
if (device != null)
|
||||
this.device = device;
|
||||
}
|
||||
|
||||
private string? _device;
|
||||
public YQueueUpdatePositionBuilder(YandexMusicApi api, string? device = null) : base(api) => _device = device;
|
||||
protected override string Method => WebRequestMethods.Http.Post;
|
||||
protected override string PathTemplate => "queues/{queueId}/update-position";
|
||||
protected override Dictionary<string, string> GetSubstitutions((string queueId, int currentIndex, bool isInteractive) tuple)
|
||||
{
|
||||
return new Dictionary<string, string> {
|
||||
{ "queueId", tuple.queueId },
|
||||
};
|
||||
}
|
||||
|
||||
protected override void SetCustomHeaders(HttpRequestHeaders headers)
|
||||
{
|
||||
headers.Add("X-Yandex-Music-Device", device);
|
||||
}
|
||||
|
||||
=> new() { { "queueId", tuple.queueId } };
|
||||
protected override NameValueCollection GetQueryParams((string queueId, int currentIndex, bool isInteractive) tuple)
|
||||
{
|
||||
return new NameValueCollection {
|
||||
=> new()
|
||||
{
|
||||
{ "currentIndex", tuple.currentIndex.ToString() },
|
||||
{ "isInteractive", tuple.isInteractive.ToString().ToLower() }
|
||||
};
|
||||
protected override void SetCustomHeaders(HttpRequestHeaders headers)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_device))
|
||||
headers.Add("X-Yandex-Music-Device", _device);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,18 @@
|
||||
using System.Net;
|
||||
using System.Net.Http.Headers;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Queue;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Queue;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Get, "queues")]
|
||||
public class YQueuesListBuilder : YRequestBuilder<YResponse<YQueueItemsContainer>, string>
|
||||
public class YQueuesListBuilder : YMusicRequestBuilder<YQueueItemsContainer?, string?>
|
||||
{
|
||||
public YQueuesListBuilder(YandexMusicApi yandex, AuthStorage auth, string? device = null) : base(yandex, auth)
|
||||
{
|
||||
if (device != null)
|
||||
this.device = device;
|
||||
}
|
||||
|
||||
private string? _device;
|
||||
public YQueuesListBuilder(YandexMusicApi api, string? device = null) : base(api) => _device = device;
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "queues";
|
||||
protected override void SetCustomHeaders(HttpRequestHeaders headers)
|
||||
{
|
||||
headers.Add("X-Yandex-Music-Device", device);
|
||||
if (!string.IsNullOrEmpty(_device))
|
||||
headers.Add("X-Yandex-Music-Device", _device);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,13 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Radio;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Radio;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Get, "rotor/station/{type}:{tag}/info")]
|
||||
public class YGetStationBuilder : YRequestBuilder<YResponse<List<YStation>>, (string type, string tag)>
|
||||
public class YGetStationBuilder : YMusicRequestBuilder<List<YStation>?, (string type, string tag)>
|
||||
{
|
||||
public YGetStationBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
public YGetStationBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "rotor/station/{type}:{tag}/info";
|
||||
protected override Dictionary<string, string> GetSubstitutions((string type, string tag) tuple)
|
||||
{
|
||||
return new Dictionary<string, string> {
|
||||
{ "type", tuple.type },
|
||||
{ "tag", tuple.tag }
|
||||
};
|
||||
}
|
||||
=> new() { { "type", tuple.type }, { "tag", tuple.tag } };
|
||||
}
|
||||
@@ -1,38 +1,21 @@
|
||||
using System.Collections.Specialized;
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Radio;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Radio;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Get, "rotor/station/{type}:{tag}/tracks")]
|
||||
public class YGetStationTracksBuilder : YRequestBuilder<YResponse<YStationSequence>, (YStationDescription station, string prevTrackId)>
|
||||
public class YGetStationTracksBuilder : YMusicRequestBuilder<YStationSequence?, (YStationDescription station, string prevTrackId)>
|
||||
{
|
||||
public YGetStationTracksBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
public YGetStationTracksBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "rotor/station/{type}:{tag}/tracks";
|
||||
protected override Dictionary<string, string> GetSubstitutions((YStationDescription station, string prevTrackId) tuple)
|
||||
{
|
||||
return new Dictionary<string, string> {
|
||||
{ "type", tuple.station.Id.Type },
|
||||
{ "tag", tuple.station.Id.Tag },
|
||||
};
|
||||
}
|
||||
|
||||
=> new() { { "type", tuple.station.Id.Type }, { "tag", tuple.station.Id.Tag } };
|
||||
protected override NameValueCollection GetQueryParams((YStationDescription station, string prevTrackId) tuple)
|
||||
{
|
||||
NameValueCollection query = new() {
|
||||
{ "settings2", "true" }
|
||||
};
|
||||
|
||||
var query = new NameValueCollection { { "settings2", "true" } };
|
||||
if (!string.IsNullOrEmpty(tuple.prevTrackId))
|
||||
query.Add("queue", tuple.prevTrackId);
|
||||
|
||||
return base.GetQueryParams(tuple);
|
||||
return query;
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,12 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Radio;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Radio;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Get, "rotor/stations/list")]
|
||||
public class YGetStationsBuilder : YRequestBuilder<YResponse<List<YStation>>, object>
|
||||
public class YGetStationsBuilder : YMusicRequestBuilder<List<YStation>?, object>
|
||||
{
|
||||
public YGetStationsBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
public YGetStationsBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "rotor/stations/list";
|
||||
}
|
||||
@@ -1,17 +1,12 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Radio;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Radio;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Get, "rotor/stations/dashboard")]
|
||||
public class YGetStationsDashboardBuilder : YRequestBuilder<YResponse<YStationsDashboard>, object>
|
||||
public class YGetStationsDashboardBuilder : YMusicRequestBuilder<YStationsDashboard?, object>
|
||||
{
|
||||
public YGetStationsDashboardBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
public YGetStationsDashboardBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "rotor/stations/dashboard";
|
||||
}
|
||||
@@ -4,42 +4,26 @@ using System.Net.Http.Json;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Radio;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Radio;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Post, "rotor/station/{type}:{tag}/settings2")]
|
||||
public class YSetSettings2Builder : YRequestBuilder<YResponse<string>, (YStationDescription station, YStationSettings2 settings2)>
|
||||
public class YSetSettings2Builder : YMusicRequestBuilder<string?, (YStationDescription station, YStationSettings2 settings2)>
|
||||
{
|
||||
public YSetSettings2Builder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
public YSetSettings2Builder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Post;
|
||||
protected override string PathTemplate => "rotor/station/{type}:{tag}/settings2";
|
||||
protected override Dictionary<string, string> GetSubstitutions((YStationDescription station, YStationSettings2 settings2) tuple)
|
||||
=> new() { { "type", tuple.station.Id.Type }, { "tag", tuple.station.Id.Tag } };
|
||||
protected override HttpContent? GetContent((YStationDescription station, YStationSettings2 settings2) tuple)
|
||||
{
|
||||
return new Dictionary<string, string> {
|
||||
{ "type", tuple.station.Id.Type },
|
||||
{ "tag", tuple.station.Id.Tag },
|
||||
};
|
||||
}
|
||||
|
||||
protected override HttpContent GetContent((YStationDescription station, YStationSettings2 settings2) tuple)
|
||||
{
|
||||
JsonSerializerOptions settings = new()
|
||||
var options = new JsonSerializerOptions
|
||||
{
|
||||
Converters = {
|
||||
new JsonStringEnumConverter()
|
||||
},
|
||||
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
|
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
||||
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
|
||||
Converters = { new JsonStringEnumConverter() }
|
||||
};
|
||||
|
||||
return JsonContent.Create(tuple.settings2, new MediaTypeHeaderValue("application/json"), settings);
|
||||
return JsonContent.Create(tuple.settings2, new MediaTypeHeaderValue("application/json"), options);
|
||||
}
|
||||
}
|
||||
@@ -5,67 +5,45 @@ using System.Net.Http.Json;
|
||||
using System.Text.Encodings.Web;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Radio;
|
||||
using YandexMusic.API.Models.Track;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Radio;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Post, "rotor/station/{type}:{tag}/feedback")]
|
||||
public class YSetStationFeedbackBuilder : YRequestBuilder<string, (YStationFeedbackType type, YStation station, YTrack track, string batchId, double totalPlayedSeconds)>
|
||||
public class YSetStationFeedbackBuilder : YMusicRequestBuilder<string?, (YStationFeedbackType type, YStation station, YTrack? track, string batchId, double totalPlayedSeconds)>
|
||||
{
|
||||
public YSetStationFeedbackBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
public YSetStationFeedbackBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Post;
|
||||
protected override string PathTemplate => "rotor/station/{type}:{tag}/feedback";
|
||||
protected override Dictionary<string, string> GetSubstitutions((YStationFeedbackType type, YStation station, YTrack? track, string batchId, double totalPlayedSeconds) tuple)
|
||||
=> new() { { "type", tuple.station.Station.Id.Type }, { "tag", tuple.station.Station.Id.Tag } };
|
||||
protected override NameValueCollection GetQueryParams((YStationFeedbackType type, YStation station, YTrack? track, string batchId, double totalPlayedSeconds) tuple)
|
||||
{
|
||||
var query = new NameValueCollection();
|
||||
if (!string.IsNullOrWhiteSpace(tuple.batchId))
|
||||
query.Add("batch-id", tuple.batchId);
|
||||
return query;
|
||||
}
|
||||
|
||||
protected override Dictionary<string, string> GetSubstitutions((YStationFeedbackType type, YStation station, YTrack track, string batchId, double totalPlayedSeconds) tuple)
|
||||
protected override HttpContent? GetContent((YStationFeedbackType type, YStation station, YTrack? track, string batchId, double totalPlayedSeconds) tuple)
|
||||
{
|
||||
return new Dictionary<string, string> {
|
||||
{ "type", tuple.station.Station.Id.Type },
|
||||
{ "tag", tuple.station.Station.Id.Tag }
|
||||
};
|
||||
}
|
||||
|
||||
protected override HttpContent GetContent((YStationFeedbackType type, YStation station, YTrack track, string batchId, double totalPlayedSeconds) tuple)
|
||||
{
|
||||
long timestamp = ((DateTimeOffset)DateTime.Now).ToUnixTimeSeconds();
|
||||
|
||||
JsonSerializerOptions settings = new()
|
||||
{
|
||||
Converters = {
|
||||
new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)
|
||||
},
|
||||
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault
|
||||
};
|
||||
|
||||
YStationFeedback feedBack = new()
|
||||
var feedback = new YStationFeedback
|
||||
{
|
||||
Type = tuple.type,
|
||||
From = tuple.station.Station.IdForFrom,
|
||||
Timestamp = timestamp
|
||||
Timestamp = DateTimeOffset.Now.ToUnixTimeSeconds()
|
||||
};
|
||||
|
||||
if (tuple.track != null)
|
||||
feedBack.TrackId = tuple.track.Id;
|
||||
|
||||
feedback.TrackId = tuple.track.Id;
|
||||
if (tuple.totalPlayedSeconds > 0)
|
||||
feedBack.TotalPlayedSeconds = tuple.totalPlayedSeconds;
|
||||
feedback.TotalPlayedSeconds = tuple.totalPlayedSeconds;
|
||||
|
||||
return JsonContent.Create(feedBack, new MediaTypeHeaderValue("application/json"), settings); ;
|
||||
}
|
||||
|
||||
protected override NameValueCollection GetQueryParams((YStationFeedbackType type, YStation station, YTrack track, string batchId, double totalPlayedSeconds) tuple)
|
||||
{
|
||||
NameValueCollection query = new();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(tuple.batchId))
|
||||
query.Add("batch-id", tuple.batchId);
|
||||
|
||||
return query;
|
||||
var options = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault,
|
||||
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
|
||||
Converters = { new JsonStringEnumConverter(JsonNamingPolicy.CamelCase) }
|
||||
};
|
||||
return JsonContent.Create(feedback, new MediaTypeHeaderValue("application/json"), options);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,21 @@
|
||||
using System.Collections.Specialized;
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Search;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Search;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Get, "search")]
|
||||
public class YSearchBuilder : YRequestBuilder<YResponse<YSearch>, (string searchText, YSearchType searchType, int page, int pageSize)>
|
||||
public class YSearchBuilder : YMusicRequestBuilder<YSearch?, (string searchText, YSearchType searchType, int page, int pageSize)>
|
||||
{
|
||||
public YSearchBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
public YSearchBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "search";
|
||||
protected override NameValueCollection GetQueryParams((string searchText, YSearchType searchType, int page, int pageSize) tuple)
|
||||
{
|
||||
return new NameValueCollection {
|
||||
=> new()
|
||||
{
|
||||
{ "text", tuple.searchText },
|
||||
{ "type", tuple.searchType.ToString() },
|
||||
{ "page", tuple.page.ToString() },
|
||||
{ "pageSize", tuple.pageSize.ToString() }
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,14 @@
|
||||
using System.Collections.Specialized;
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Search;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Search;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Get, "search/suggest")]
|
||||
public class YSearchSuggestBuilder : YRequestBuilder<YResponse<YSearchSuggest>, string>
|
||||
public class YSearchSuggestBuilder : YMusicRequestBuilder<YSearchSuggest?, string>
|
||||
{
|
||||
public YSearchSuggestBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
public YSearchSuggestBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "search/suggest";
|
||||
protected override NameValueCollection GetQueryParams(string searchText)
|
||||
{
|
||||
return new NameValueCollection {
|
||||
{ "part", searchText }
|
||||
};
|
||||
}
|
||||
=> new() { { "part", searchText } };
|
||||
}
|
||||
@@ -1,24 +1,13 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Track;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Track;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Get, "tracks/{trackId}/similar")]
|
||||
public class YGetTrackSimilarBuilder : YRequestBuilder<YResponse<YTrackSimilar>, string>
|
||||
public class YGetTrackSimilarBuilder : YMusicRequestBuilder<YTrackSimilar?, string>
|
||||
{
|
||||
public YGetTrackSimilarBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
public YGetTrackSimilarBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "tracks/{trackId}/similar";
|
||||
protected override Dictionary<string, string> GetSubstitutions(string trackId)
|
||||
{
|
||||
return new Dictionary<string, string> {
|
||||
{ "trackId", trackId }
|
||||
};
|
||||
}
|
||||
=> new() { { "trackId", trackId } };
|
||||
}
|
||||
@@ -1,24 +1,13 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Track;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Track;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Get, "tracks/{trackId}/supplement")]
|
||||
public class YGetTrackSupplementBuilder : YRequestBuilder<YResponse<YTrackSupplement>, string>
|
||||
public class YGetTrackSupplementBuilder : YMusicRequestBuilder<YTrackSupplement?, string>
|
||||
{
|
||||
public YGetTrackSupplementBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
public YGetTrackSupplementBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "tracks/{trackId}/supplement";
|
||||
protected override Dictionary<string, string> GetSubstitutions(string trackId)
|
||||
{
|
||||
return new Dictionary<string, string> {
|
||||
{ "trackId", trackId }
|
||||
};
|
||||
}
|
||||
=> new() { { "trackId", trackId } };
|
||||
}
|
||||
@@ -1,25 +1,13 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Models.Track;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Track;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Post, "tracks")]
|
||||
public class YGetTracksBuilder : YRequestBuilder<YResponse<List<YTrack>>, IEnumerable<string>>
|
||||
public class YGetTracksBuilder : YMusicRequestBuilder<List<YTrack>?, IEnumerable<string>>
|
||||
{
|
||||
public YGetTracksBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
protected override HttpContent GetContent(IEnumerable<string> trackIds)
|
||||
{
|
||||
return new FormUrlEncodedContent(new Dictionary<string, string> {
|
||||
{ "track-ids", string.Join(",", trackIds) },
|
||||
{ "with-positions", "true" }
|
||||
});
|
||||
}
|
||||
public YGetTracksBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Post;
|
||||
protected override string PathTemplate => "tracks";
|
||||
protected override HttpContent? GetContent(IEnumerable<string> trackIds)
|
||||
=> new FormUrlEncodedContent(new Dictionary<string, string> { { "track-ids", string.Join(",", trackIds) }, { "with-positions", "true" } });
|
||||
}
|
||||
@@ -1,37 +1,31 @@
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Track;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Track;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Post, "play-audio")]
|
||||
public class YSendTrackInfoBuilder : YRequestBuilder<string, (YTrack track, string from, bool fromCache, string playId, string playlistId, double totalPlayedSeconds, double endPositionSeconds)>
|
||||
public class YSendTrackInfoBuilder : YMusicRequestBuilder<string?, (YTrack track, string from, bool fromCache, string playId, string playlistId, double totalPlayedSeconds, double endPositionSeconds)>
|
||||
{
|
||||
public YSendTrackInfoBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
public YSendTrackInfoBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Post;
|
||||
protected override string PathTemplate => "play-audio";
|
||||
protected override HttpContent? GetContent((YTrack track, string from, bool fromCache, string playId, string playlistId, double totalPlayedSeconds, double endPositionSeconds) tuple)
|
||||
{
|
||||
}
|
||||
|
||||
protected override HttpContent GetContent((YTrack track, string from, bool fromCache, string playId, string playlistId, double totalPlayedSeconds, double endPositionSeconds) tuple)
|
||||
{
|
||||
Dictionary<string, string> formData = new() {
|
||||
var form = new Dictionary<string, string>
|
||||
{
|
||||
{ "track_id", tuple.track.Id },
|
||||
{ "from-cache", tuple.fromCache.ToString() },
|
||||
{ "play_id", tuple.playId },
|
||||
{ "uid", storage.User.Uid },
|
||||
{ "uid", Api.Storage.User.Uid },
|
||||
{ "timestamp", DateTime.Now.ToString("o", CultureInfo.InvariantCulture) },
|
||||
{ "client-now", DateTime.Now.ToString("o", CultureInfo.InvariantCulture) },
|
||||
{ "album-id", tuple.track.Albums.FirstOrDefault()?.Id },
|
||||
{ "album-id", tuple.track.Albums?.FirstOrDefault()?.Id ?? "" },
|
||||
{ "from", tuple.from },
|
||||
{ "playlist-id", tuple.playlistId },
|
||||
{ "track-length-seconds", ((double)(tuple.track.DurationMs / 1000)).ToString(CultureInfo.InvariantCulture) },
|
||||
{ "track-length-seconds", (tuple.track.DurationMs / 1000.0).ToString(CultureInfo.InvariantCulture) },
|
||||
{ "total-played-seconds", tuple.totalPlayedSeconds.ToString(CultureInfo.InvariantCulture) },
|
||||
{ "end-position-seconds", tuple.endPositionSeconds.ToString(CultureInfo.InvariantCulture) },
|
||||
{ "end-position-seconds", tuple.endPositionSeconds.ToString(CultureInfo.InvariantCulture) }
|
||||
};
|
||||
|
||||
return new FormUrlEncodedContent(formData);
|
||||
return new FormUrlEncodedContent(form);
|
||||
}
|
||||
}
|
||||
@@ -1,42 +1,34 @@
|
||||
using System.Collections.Specialized;
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Track;
|
||||
|
||||
[YRequest(WebRequestMethods.Http.Get, "{src}")]
|
||||
public class YStorageDownloadFileBuilder : YRequestBuilder<YStorageDownloadFile, string>
|
||||
/// <summary>Особый запрос – не к api.music.yandex.net, а к произвольному URL.</summary>
|
||||
public class YStorageDownloadFileBuilder : YJsonRequestBuilder<YStorageDownloadFile?, string>
|
||||
{
|
||||
public YStorageDownloadFileBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
public YStorageDownloadFileBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string BaseUrl => ""; // не используется, т.к. URL берётся из параметра
|
||||
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
|
||||
protected override string PathTemplate => "{src}";
|
||||
|
||||
protected override Dictionary<string, string> GetSubstitutions(string src)
|
||||
{
|
||||
return new Dictionary<string, string> {
|
||||
{ "src", src.Split('?')[0] }
|
||||
};
|
||||
}
|
||||
|
||||
=> new() { { "src", src.Split('?')[0] } };
|
||||
protected override NameValueCollection GetQueryParams(string src)
|
||||
{
|
||||
NameValueCollection query = new() {
|
||||
{ "format", "json" }
|
||||
};
|
||||
|
||||
src.Split('?')[1]
|
||||
.Split('&')
|
||||
.ToList()
|
||||
.ForEach(p =>
|
||||
var query = new NameValueCollection { { "format", "json" } };
|
||||
var parts = src.Split('?');
|
||||
if (parts.Length > 1)
|
||||
{
|
||||
foreach (var param in parts[1].Split('&'))
|
||||
{
|
||||
string[] param = p.Split('=');
|
||||
query.Add(param[0], param[1]);
|
||||
});
|
||||
|
||||
var kv = param.Split('=');
|
||||
if (kv.Length == 2) query.Add(kv[0], kv[1]);
|
||||
}
|
||||
}
|
||||
return query;
|
||||
}
|
||||
}
|
||||
@@ -1,31 +1,16 @@
|
||||
using System.Collections.Specialized;
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Track;
|
||||
|
||||
[YApiRequest(WebRequestMethods.Http.Get, "tracks/{trackKey}/download-info")]
|
||||
public class YTrackDownloadInfoBuilder : YRequestBuilder<YResponse<List<YTrackDownloadInfo>>, (string trackKey, bool direct)>
|
||||
public class YTrackDownloadInfoBuilder : YMusicRequestBuilder<List<YTrackDownloadInfo>?, (string trackKey, bool direct)>
|
||||
{
|
||||
public YTrackDownloadInfoBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
public YTrackDownloadInfoBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "tracks/{trackKey}/download-info";
|
||||
protected override Dictionary<string, string> GetSubstitutions((string trackKey, bool direct) tuple)
|
||||
{
|
||||
return new Dictionary<string, string> {
|
||||
{ "trackKey", tuple.trackKey }
|
||||
};
|
||||
}
|
||||
|
||||
=> new() { { "trackKey", tuple.trackKey } };
|
||||
protected override NameValueCollection GetQueryParams((string trackKey, bool direct) tuple)
|
||||
{
|
||||
return new NameValueCollection {
|
||||
{ "direct", tuple.direct.ToString() }
|
||||
};
|
||||
}
|
||||
=> new() { { "direct", tuple.direct.ToString() } };
|
||||
}
|
||||
@@ -1,32 +1,24 @@
|
||||
using System.Collections.Specialized;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Playlist;
|
||||
using YandexMusic.API.Models.Ugc;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Ugc;
|
||||
|
||||
[YWebApiRequest(WebRequestMethods.Http.Get, "handlers/ugc-upload.jsx")]
|
||||
public class YUgcGetUploadLinkBuilder : YRequestBuilder<YUgcUpload, (YPlaylist playlist, string fileName)>
|
||||
public class YUgcGetUploadLinkBuilder : YMusicRequestBuilder<YUgcUpload?, (YPlaylist playlist, string fileName)>
|
||||
{
|
||||
private static readonly Lazy<Random> Random = new(() => new Random());
|
||||
|
||||
public YUgcGetUploadLinkBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
|
||||
private static readonly Random _random = new();
|
||||
public YUgcGetUploadLinkBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string Method => WebRequestMethods.Http.Get;
|
||||
protected override string PathTemplate => "handlers/ugc-upload.jsx";
|
||||
protected override NameValueCollection GetQueryParams((YPlaylist playlist, string fileName) tuple)
|
||||
{
|
||||
return new NameValueCollection {
|
||||
=> new()
|
||||
{
|
||||
{ "filename", tuple.fileName },
|
||||
{ "kind", tuple.playlist.Kind },
|
||||
{ "visibility", "private" },
|
||||
{ "external-domain", "music.yandex.ru" },
|
||||
{ "ncrnd", Random.Value.NextDouble().ToString(CultureInfo.InvariantCulture) }
|
||||
{ "ncrnd", _random.NextDouble().ToString(CultureInfo.InvariantCulture) }
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,31 +1,21 @@
|
||||
using System.Net;
|
||||
|
||||
using YandexMusic.API.Common;
|
||||
using YandexMusic.API.Models.Common;
|
||||
using YandexMusic.API.Requests.Common;
|
||||
using YandexMusic.API.Requests.Common.Attributes;
|
||||
|
||||
namespace YandexMusic.API.Requests.Ugc;
|
||||
|
||||
[YRequest(WebRequestMethods.Http.Post, "{postTargetLink}")]
|
||||
public class YUgcUploadBuilder : YRequestBuilder<YResponse<string>, (string postTargetLink, byte[] fileBytes)>
|
||||
/// <summary>Загрузка трека – специальный запрос на произвольный URL.</summary>
|
||||
public class YUgcUploadBuilder : YJsonRequestBuilder<YResponse<string>?, (string postTargetLink, byte[] fileBytes)>
|
||||
{
|
||||
public YUgcUploadBuilder(YandexMusicApi yandex, AuthStorage auth) : base(yandex, auth)
|
||||
{
|
||||
}
|
||||
public YUgcUploadBuilder(YandexMusicApi api) : base(api) { }
|
||||
protected override string BaseUrl => "";
|
||||
|
||||
protected override string Method => WebRequestMethods.Http.Post;
|
||||
|
||||
protected override string PathTemplate => "{postTargetLink}";
|
||||
|
||||
protected override Dictionary<string, string> GetSubstitutions((string postTargetLink, byte[] fileBytes) tuple)
|
||||
{
|
||||
return new Dictionary<string, string> {
|
||||
{ "postTargetLink", tuple.postTargetLink }
|
||||
};
|
||||
}
|
||||
|
||||
protected override HttpContent GetContent((string postTargetLink, byte[] fileBytes) tuple)
|
||||
{
|
||||
return new MultipartFormDataContent {
|
||||
{ new ByteArrayContent(tuple.fileBytes), "file" }
|
||||
};
|
||||
}
|
||||
|
||||
=> new() { { "postTargetLink", tuple.postTargetLink } };
|
||||
protected override HttpContent? GetContent((string postTargetLink, byte[] fileBytes) tuple)
|
||||
=> new MultipartFormDataContent { { new ByteArrayContent(tuple.fileBytes), "file" } };
|
||||
}
|
||||
Reference in New Issue
Block a user