Полный рефакторинг api. Вынесено отдельно api passport

This commit is contained in:
2026-04-20 23:30:01 +03:00
parent 34261d02a9
commit eb1eba0162
61 changed files with 1074 additions and 640 deletions

View File

@@ -3,7 +3,7 @@ using YandexMusic.API.Models.Account;
namespace YandexMusic.API.Requests.Account;
internal class YGetAuthAppPasswordBuilder : YAuthRequestBuilder<YAuthBase?, string>
internal class YGetAuthAppPasswordBuilder : YPassportRequestBuilder<YAuthBase?, string>
{
public YGetAuthAppPasswordBuilder(YandexMusicApi api) : base(api) { }
protected override string Method => WebRequestMethods.Http.Post;

View File

@@ -3,7 +3,7 @@ using YandexMusic.API.Models.Account;
namespace YandexMusic.API.Requests.Account;
internal class YGetAuthCaptchaBuilder : YAuthRequestBuilder<YAuthCaptcha?, object>
internal class YGetAuthCaptchaBuilder : YPassportRequestBuilder<YAuthCaptcha?, object>
{
public YGetAuthCaptchaBuilder(YandexMusicApi api) : base(api) { }
protected override string Method => WebRequestMethods.Http.Post;

View File

@@ -5,7 +5,7 @@ using YandexMusic.API.Requests.Common;
namespace YandexMusic.API.Requests.Account;
internal class YGetAuthCookiesBuilder : YAuthRequestBuilder<YAccessToken?, object>
internal class YGetAuthCookiesBuilder : YPassportRequestBuilder<YAccessToken?, object>
{
public YGetAuthCookiesBuilder(YandexMusicApi api) : base(api) { }
protected override string Method => WebRequestMethods.Http.Post;

View File

@@ -3,7 +3,7 @@ using YandexMusic.API.Models.Account;
namespace YandexMusic.API.Requests.Account;
internal class YGetAuthLetterBuilder : YAuthRequestBuilder<YAuthLetter?, object>
internal class YGetAuthLetterBuilder : YPassportRequestBuilder<YAuthLetter?, object>
{
public YGetAuthLetterBuilder(YandexMusicApi api) : base(api) { }
protected override string Method => WebRequestMethods.Http.Post;

View File

@@ -3,7 +3,7 @@ using YandexMusic.API.Models.Account;
namespace YandexMusic.API.Requests.Account;
internal class YGetAuthLoginCaptchaBuilder : YAuthRequestBuilder<YAuthBase?, string>
internal class YGetAuthLoginCaptchaBuilder : YPassportRequestBuilder<YAuthBase?, string>
{
public YGetAuthLoginCaptchaBuilder(YandexMusicApi api) : base(api) { }
protected override string Method => WebRequestMethods.Http.Post;

View File

@@ -3,7 +3,7 @@ using YandexMusic.API.Models.Account;
namespace YandexMusic.API.Requests.Account;
internal class YGetAuthLoginLetterBuilder : YAuthRequestBuilder<YAuthLetterStatus?, object>
internal class YGetAuthLoginLetterBuilder : YPassportRequestBuilder<YAuthLetterStatus?, object>
{
public YGetAuthLoginLetterBuilder(YandexMusicApi api) : base(api) { }
protected override string Method => WebRequestMethods.Http.Post;

View File

@@ -3,7 +3,7 @@ using YandexMusic.API.Models.Account;
namespace YandexMusic.API.Requests.Account;
internal class YGetAuthLoginUserBuilder : YAuthRequestBuilder<YAuthTypes?, (string token, string login)>
internal class YGetAuthLoginUserBuilder : YPassportRequestBuilder<YAuthTypes?, (string token, string login)>
{
public YGetAuthLoginUserBuilder(YandexMusicApi api) : base(api) { }
protected override string Method => WebRequestMethods.Http.Post;

View File

@@ -1,19 +0,0 @@
using System.Net;
using System.Net.Http.Headers;
using YandexMusic.API.Models.Account;
namespace YandexMusic.API.Requests.Account;
internal class YGetAuthQRBuilder : YAuthRequestBuilder<YAuthQR?, object>
{
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)
{
headers.Add("X-Csrf-Token", Api.Storage.HeaderToken.CsfrToken);
headers.Add("Process-Uuid", Api.Storage.HeaderToken.ProcessUuid);
}
}

View File

@@ -3,7 +3,7 @@ using YandexMusic.API.Models.Account;
namespace YandexMusic.API.Requests.Account;
internal class YGetLoginInfoBuilder : YAuthRequestBuilder<YLoginInfo?, object>
internal class YGetLoginInfoBuilder : YPassportRequestBuilder<YLoginInfo?, object>
{
public YGetLoginInfoBuilder(YandexMusicApi api) : base(api) { }
protected override string Method => WebRequestMethods.Http.Get;

View File

@@ -5,7 +5,7 @@ using YandexMusic.API.Models.Account;
namespace YandexMusic.API.Requests.Account;
internal class YGetShortAccountInfoBuilder : YAuthRequestBuilder<YShortAccountInfo?, object>
internal class YGetShortAccountInfoBuilder : YPassportRequestBuilder<YShortAccountInfo?, object>
{
public YGetShortAccountInfoBuilder(YandexMusicApi api) : base(api) { }
protected override string Method => WebRequestMethods.Http.Get;

View File

@@ -4,7 +4,7 @@ using YandexMusic.API.Models.Account;
namespace YandexMusic.API.Requests.Account;
internal class YPostAuthStats : YAuthRequestBuilder<YAuthEmpty?, object>
internal class YPostAuthStats : YPassportRequestBuilder<YAuthEmpty?, object>
{
public YPostAuthStats(YandexMusicApi api) : base(api) { }
protected override string Method => WebRequestMethods.Http.Post;

View File

@@ -1,23 +0,0 @@
using System.Net;
using System.Net.Http.Headers;
using YandexMusic.API.Models.Account;
namespace YandexMusic.API.Requests.Account;
internal class YPostQrStatus : YAuthRequestBuilder<YAuthQRStatus?, object>
{
public YPostQrStatus(YandexMusicApi api) : base(api) { }
protected override string Method => WebRequestMethods.Http.Post;
protected override string PathTemplate => "pwl-yandex/api/passport/auth/magic/code/status";
protected override HttpContent? GetContent(object _)
=> new FormUrlEncodedContent(new Dictionary<string, string>
{
["csrf_token"] = Api.Storage.AuthToken.CsfrToken,
["track_id"] = Api.Storage.AuthToken.TrackId,
});
protected override void SetCustomHeaders(HttpRequestHeaders headers)
{
headers.Add("X-Csrf-Token", Api.Storage.HeaderToken.CsfrToken);
headers.Add("Process-Uuid", Api.Storage.HeaderToken.ProcessUuid);
}
}

View File

@@ -12,5 +12,8 @@ internal class YGetArtistTrackBuilder : YMusicRequestBuilder<YTracksPage?, (stri
protected override Dictionary<string, string> GetSubstitutions((string id, int page, int pageSize) tuple)
=> new() { { "artistId", tuple.id } };
protected override NameValueCollection GetQueryParams((string id, int page, int pageSize) tuple)
=> new() { { "page", tuple.page.ToString() }, { "pageSize", tuple.pageSize.ToString() } };
=> new() {
{ "page", tuple.page.ToString() },
{ "pageSize", tuple.pageSize.ToString() },
};
}

View File

@@ -4,15 +4,20 @@ using YandexMusic.API.Requests.Common;
namespace YandexMusic.API.Requests;
/// <summary>Базовый класс для запросов к Passport (passport.yandex.ru).</summary>
internal abstract class YAuthRequestBuilder<TResponse, TParams> : YJsonRequestBuilder<TResponse, TParams>
internal abstract class YPassportRequestBuilder<TResponse, TParams> : YJsonRequestBuilder<TResponse, TParams>
{
protected override string BaseUrl => YConstants.Endpoints.PassportUrl;
protected YAuthRequestBuilder(YandexMusicApi api) : base(api) { }
protected YPassportRequestBuilder(YandexMusicApi api) : base(api) { }
protected override void SetCustomHeaders(HttpRequestHeaders headers)
{
base.SetCustomHeaders(headers);
headers.Add("X-Requested-With", "XMLHttpRequest");
if (Api.Storage.HeaderToken != null)
{
headers.Add("X-Csrf-Token", Api.Storage.HeaderToken.CsfrToken);
headers.Add("Process-Uuid", Api.Storage.HeaderToken.ProcessUuid);
}
}
}

View File

@@ -0,0 +1,27 @@
using System.Net;
using System.Net.Http.Json;
using YandexMusic.API.Models.Passport;
namespace YandexMusic.API.Requests.Passport;
internal class YCheckPhoneAvailabilityBuilder : YPassportRequestBuilder<YCheckAvailabilityResult?, string>
{
public YCheckPhoneAvailabilityBuilder(YandexMusicApi api) : base(api) { }
protected override string Method => WebRequestMethods.Http.Post;
protected override string PathTemplate => "pwl-yandex/api/passport/suggest/check_availability";
protected override HttpContent? GetContent(string phone)
{
var data = new
{
track_id = Api.Storage.AuthToken.TrackId,
phone_number = phone,
can_use_anmon = true,
check_for_push = true,
push_suggest_log_all_subscriptions = false
};
return JsonContent.Create(data);
}
}

View File

@@ -0,0 +1,24 @@
using System.Net;
using System.Net.Http.Json;
using YandexMusic.API.Models.Account;
namespace YandexMusic.API.Requests.Passport;
internal class YCheckPushCodeBuilder : YPassportRequestBuilder<YAuthEmpty?, string>
{
public YCheckPushCodeBuilder(YandexMusicApi api) : base(api) { }
protected override string Method => WebRequestMethods.Http.Post;
protected override string PathTemplate => "pwl-yandex/api/passport/auth/check-push-code";
protected override HttpContent? GetContent(string code)
{
var data = new
{
track_id = Api.Storage.AuthToken.TrackId,
code
};
return JsonContent.Create(data);
}
}

View File

@@ -0,0 +1,19 @@
using System.Net;
using System.Net.Http.Json;
using YandexMusic.API.Models.Passport;
namespace YandexMusic.API.Requests.Passport;
internal class YCheckSessionBuilder : YPassportRequestBuilder<YPassportSessionStatus?, object>
{
public YCheckSessionBuilder(YandexMusicApi api) : base(api) { }
protected override string Method => WebRequestMethods.Http.Post;
protected override string PathTemplate => "pwl-yandex/api/passport/sessions/check_session";
protected override HttpContent? GetContent(object _)
{
var data = new { track_id = Api.Storage.AuthToken.TrackId };
return JsonContent.Create(data);
}
}

View File

@@ -0,0 +1,13 @@
using System.Net;
using YandexMusic.API.Models.Passport;
namespace YandexMusic.API.Requests.Passport;
internal class YCreateTrackBuilder : YPassportRequestBuilder<YPassportTrack?, object>
{
public YCreateTrackBuilder(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", "" } });
}

View File

@@ -1,10 +1,9 @@
using System.Net;
using System.Net.Http.Headers;
using YandexMusic.API.Models.Account;
using YandexMusic.API.Models.Passport;
namespace YandexMusic.API.Requests.Account;
namespace YandexMusic.API.Requests.Passport;
internal class YGetAuthLoginQRBuilder : YAuthRequestBuilder<YAuthQRSession, string>
internal class YGetAuthLoginQRBuilder : YPassportRequestBuilder<YAuthQrSession, string>
{
public YGetAuthLoginQRBuilder(YandexMusicApi yandex) : base(yandex)
{
@@ -20,9 +19,4 @@ internal class YGetAuthLoginQRBuilder : YAuthRequestBuilder<YAuthQRSession, stri
{ "track_id", Api.Storage.AuthToken.SessionTrackId }
});
}
protected override void SetCustomHeaders(HttpRequestHeaders headers)
{
headers.Add("X-Csrf-Token", Api.Storage.HeaderToken.CsfrToken);
headers.Add("Process-Uuid", Api.Storage.HeaderToken.ProcessUuid);
}
}

View File

@@ -3,21 +3,21 @@ using System.Net.Http.Headers;
using YandexMusic.API.Models.Account;
using YandexMusic.API.Requests.Common;
namespace YandexMusic.API.Requests.Account;
namespace YandexMusic.API.Requests.Passport;
internal class YGetMusicTokenBuilder : YAuthRequestBuilder<YAccessToken?, object>
internal class YGetMusicTokenBuilder : YPassportRequestBuilder<YAccessToken?, string>
{
public YGetMusicTokenBuilder(YandexMusicApi api) : base(api) { }
protected override string BaseUrl => YConstants.Endpoints.MobilePassportUrl;
protected override string Method => WebRequestMethods.Http.Post;
protected override string PathTemplate => "/1/token";
protected override HttpContent? GetContent(object _)
protected override HttpContent? GetContent(string passportToken)
=> new FormUrlEncodedContent(new Dictionary<string, string>
{
{ "client_id", YConstants.ClientId },
{ "client_secret", YConstants.ClientSecret },
{ "grant_type", "x-token" },
{ "access_token", Api.Storage.AccessToken.AccessToken }
{ "access_token", passportToken }
});
protected override void SetCustomHeaders(HttpRequestHeaders headers)
{

View File

@@ -0,0 +1,17 @@
using System.Net;
using YandexMusic.API.Models.Passport;
namespace YandexMusic.API.Requests.Passport;
internal class YGetQrStatus : YPassportRequestBuilder<YAuthQRStatus?, object>
{
public YGetQrStatus(YandexMusicApi api) : base(api) { }
protected override string Method => WebRequestMethods.Http.Post;
protected override string PathTemplate => "pwl-yandex/api/passport/auth/magic/code/status";
protected override HttpContent? GetContent(object _)
=> new FormUrlEncodedContent(new Dictionary<string, string>
{
["csrf_token"] = Api.Storage.AuthToken.CsfrToken,
["track_id"] = Api.Storage.AuthToken.TrackId,
});
}

View File

@@ -0,0 +1,20 @@
using System.Net;
using System.Net.Http.Json;
using YandexMusic.API.Models.Passport;
namespace YandexMusic.API.Requests.Passport;
internal class YGetSessionBuilder : YPassportRequestBuilder<YPassportSession?, object>
{
public YGetSessionBuilder(YandexMusicApi api) : base(api) { }
protected override string Method => WebRequestMethods.Http.Post;
protected override string PathTemplate => "pwl-yandex/api/passport/sessions/get_session";
protected override HttpContent? GetContent(object _)
{
var data = new { track_id = Api.Storage.AuthToken.TrackId };
return JsonContent.Create(data);
}
}

View File

@@ -0,0 +1,23 @@
using System.Net;
using System.Net.Http.Json;
using YandexMusic.API.Models.Passport;
namespace YandexMusic.API.Requests.Passport;
internal class YMultiStepPasswordBuilder : YPassportRequestBuilder<YPassportUser?, string>
{
public YMultiStepPasswordBuilder(YandexMusicApi api) : base(api) { }
protected override string Method => WebRequestMethods.Http.Post;
protected override string PathTemplate => "pwl-yandex/api/passport/auth/multistep_password";
protected override HttpContent? GetContent(string password)
{
var data = new
{
track_id = Api.Storage.AuthToken.TrackId,
password
};
return JsonContent.Create(data);
}
}

View File

@@ -0,0 +1,35 @@
using System.Net;
using System.Net.Http.Json;
using YandexMusic.API.Models.Passport;
namespace YandexMusic.API.Requests.Passport;
internal class YMultistepStartBuilder : YPassportRequestBuilder<YMultistepStart?, string>
{
public YMultistepStartBuilder(YandexMusicApi api) : base(api) { }
protected override string Method => WebRequestMethods.Http.Post;
protected override string PathTemplate => "pwl-yandex/api/passport/auth/multistep_start";
protected override HttpContent? GetContent(string login)
{
var data = new
{
login,
track_id = Api.Storage.AuthToken.TrackId,
display_language = "ru",
retpath = string.Empty,
can_send_push_code = true,
check_for_xtokens_for_pictures = false,
force_check_for_protocols = true,
app_id = "ru.yandex.music",
am_version_name = "7.50.2(750024597)",
app_platform = "android",
app_version_name = "2026.02.3 #135rur",
device_id = Api.Storage.DeviceId,
device_connection_type = "9"
};
return JsonContent.Create(data);
}
}

View File

@@ -0,0 +1,23 @@
using System.Net;
using System.Net.Http.Json;
using YandexMusic.API.Models.Passport;
namespace YandexMusic.API.Requests.Passport;
internal class YRfcOtpBuilder : YPassportRequestBuilder<YPassportUser?, string>
{
public YRfcOtpBuilder(YandexMusicApi api) : base(api) { }
protected override string Method => WebRequestMethods.Http.Post;
protected override string PathTemplate => "pwl-yandex/api/passport/auth/rfc-otp";
protected override HttpContent? GetContent(string otp)
{
var data = new
{
track_id = Api.Storage.AuthToken.TrackId,
otp
};
return JsonContent.Create(data);
}
}

View File

@@ -0,0 +1,26 @@
using System.Net;
using System.Net.Http.Json;
using YandexMusic.API.Models.Passport;
namespace YandexMusic.API.Requests.Passport;
internal class YSendPushBuilder : YPassportRequestBuilder<YSendPushResult?, string>
{
public YSendPushBuilder(YandexMusicApi api) : base(api) { }
protected override string Method => WebRequestMethods.Http.Post;
protected override string PathTemplate => "pwl-yandex/api/passport/auth/suggest-send-push";
protected override HttpContent? GetContent(string phone)
{
var data = new
{
track_id = Api.Storage.AuthToken.TrackId,
phone_number = phone,
can_use_anmon = true,
force_show_code_in_notification = "1",
country = Api.Storage.Country
};
return JsonContent.Create(data);
}
}

View File

@@ -0,0 +1,23 @@
using System.Net;
using System.Net.Http.Json;
using YandexMusic.API.Models.Passport;
namespace YandexMusic.API.Requests.Passport;
internal class YSuggestByPhoneBuilder : YPassportRequestBuilder<YSuggestByPhoneResult?, object>
{
public YSuggestByPhoneBuilder(YandexMusicApi api) : base(api) { }
protected override string Method => WebRequestMethods.Http.Post;
protected override string PathTemplate => "pwl-yandex/api/passport/suggest/by_phone";
protected override HttpContent? GetContent(object _)
{
var data = new
{
track_id = Api.Storage.AuthToken.TrackId,
can_use_anmon = true
};
return JsonContent.Create(data);
}
}

View File

@@ -0,0 +1,24 @@
using System.Net;
using System.Net.Http.Json;
using YandexMusic.API.Models.Passport;
namespace YandexMusic.API.Requests.Passport;
internal class YValidatePhoneNumberBuilder : YPassportRequestBuilder<YValidatePhoneNumberResult?, string>
{
public YValidatePhoneNumberBuilder(YandexMusicApi api) : base(api) { }
protected override string Method => WebRequestMethods.Http.Post;
protected override string PathTemplate => "pwl-yandex/api/passport/validate/phone_number";
protected override HttpContent? GetContent(string phone)
{
var data = new
{
track_id = Api.Storage.AuthToken.TrackId,
phone_number = phone,
country = Api.Storage.Country
};
return JsonContent.Create(data);
}
}

View File

@@ -0,0 +1,25 @@
using System.Net;
using System.Net.Http.Json;
using YandexMusic.API.Models.Passport;
namespace YandexMusic.API.Requests.Passport;
internal class YValidateSquatterBuilder : YPassportRequestBuilder<YValidateSquatter?, string>
{
public YValidateSquatterBuilder(YandexMusicApi api) : base(api) { }
protected override string Method => WebRequestMethods.Http.Post;
protected override string PathTemplate => "pwl-yandex/api/passport/validate/squatter";
protected override HttpContent? GetContent(string phone)
{
var data = new
{
track_id = Api.Storage.AuthToken.TrackId,
phone_number = phone,
scenario = "auth",
can_use_anmon = true
};
return JsonContent.Create(data);
}
}

View File

@@ -9,11 +9,11 @@ namespace YandexMusic.API.Requests.Track;
internal class YStorageDownloadFileBuilder : YJsonRequestBuilder<YStorageDownloadFile?, string>
{
public YStorageDownloadFileBuilder(YandexMusicApi api) : base(api) { }
protected override string BaseUrl => ""; // не используется, т.к. URL берётся из параметра
protected override string BaseUrl => "{src}"; // не используется, т.к. URL берётся из параметра
protected override string Method => WebRequestMethods.Http.Get;
protected override string PathTemplate => "{src}";
protected override string PathTemplate => "";
protected override Dictionary<string, string> GetSubstitutions(string src)
=> new() { { "src", src.Split('?')[0] } };
@@ -26,7 +26,7 @@ internal class YStorageDownloadFileBuilder : YJsonRequestBuilder<YStorageDownloa
foreach (var param in parts[1].Split('&'))
{
var kv = param.Split('=');
if (kv.Length == 2) query.Add(kv[0], kv[1]);
if (kv.Length >= 2) query.Add(kv[0], kv[1]);
}
}
return query;

View File

@@ -8,11 +8,11 @@ namespace YandexMusic.API.Requests.Ugc;
internal class YUgcUploadBuilder : YJsonRequestBuilder<YResponse<string>?, (string postTargetLink, byte[] fileBytes)>
{
public YUgcUploadBuilder(YandexMusicApi api) : base(api) { }
protected override string BaseUrl => "";
protected override string BaseUrl => "{postTargetLink}";
protected override string Method => WebRequestMethods.Http.Post;
protected override string PathTemplate => "{postTargetLink}";
protected override string PathTemplate => "";
protected override Dictionary<string, string> GetSubstitutions((string postTargetLink, byte[] fileBytes) tuple)
=> new() { { "postTargetLink", tuple.postTargetLink } };