Files
YandexMusic/YandexMusic.API/Requests/Common/YRequestBuilder.cs
2026-04-10 12:12:33 +03:00

159 lines
4.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Collections.Specialized;
using System.Net;
using System.Net.Http.Headers;
using System.Reflection;
using System.Text;
using System.Web;
using YandexMusic.API.Common;
using YandexMusic.API.Extensions;
using YandexMusic.API.Requests.Common.Attributes;
namespace YandexMusic.API.Requests.Common
{
public class YRequestBuilder<ResponseType, ParamsTuple>
{
#region Поля
private readonly JsonSerializerSettings jsonSettings = new()
{
Converters = new List<JsonConverter> {
new StringEnumConverter {
NamingStrategy = new CamelCaseNamingStrategy()
}
},
NullValueHandling = NullValueHandling.Ignore,
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
private YRequestAttribute requestInfo;
private Dictionary<string, string> subs;
protected YandexMusicApi api;
protected AuthStorage storage;
protected string device;
#endregion Поля
#region Свойства
protected YandexMusicApi API => api;
protected AuthStorage Storage => storage;
#endregion Свойства
#region Вспомогательные функции
private Uri BuildUri(ParamsTuple tuple)
{
NameValueCollection queryParams = GetQueryParams(tuple);
NameValueCollection modifiedParams = HttpUtility.ParseQueryString(string.Empty);
// Подстановка в параметры
foreach (string key in queryParams.Keys)
{
modifiedParams.Set(key, ReplaceSubs(queryParams.Get(key)));
}
string endpoint = ReplaceSubs(requestInfo.Url);
UriBuilder builder = new(endpoint)
{
Query = modifiedParams.ToString() ?? string.Empty
};
return builder.Uri;
}
private HttpRequestMessage CreateMessage(ParamsTuple tuple)
{
HttpRequestMessage msg = new()
{
RequestUri = BuildUri(tuple),
Method = new HttpMethod(requestInfo.Method),
Content = GetContent(tuple)
};
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}");
SetCustomHeaders(msg.Headers);
return msg;
}
protected string ReplaceSubs(string str)
{
string[] sub = str.GetMatches(@"\{.+?\}");
foreach (string s in sub)
{
if (!subs.TryGetValue(s.ReplaceRegex(@"[\{\}]", string.Empty), out string value))
throw new Exception($"Не найдена подстановка {s}");
str = str.Replace(s, value);
}
return str;
}
protected virtual Dictionary<string, string> GetSubstitutions(ParamsTuple tuple)
{
return new Dictionary<string, string>();
}
protected virtual NameValueCollection GetQueryParams(ParamsTuple tuple)
{
return new NameValueCollection();
}
protected virtual HttpContent GetContent(ParamsTuple tuple)
{
return null;
}
protected virtual void SetCustomHeaders(HttpRequestHeaders headers)
{
}
protected string SerializeJson(object data)
{
return JsonConvert.SerializeObject(data, jsonSettings);
}
#endregion Вспомогательные функции
public YRequestBuilder(YandexMusicApi yandex, AuthStorage auth)
{
requestInfo = GetType()
.GetCustomAttributes<YRequestAttribute>()
.FirstOrDefault();
if (requestInfo == null)
throw new NotImplementedException($"Отсутствует атрибут {nameof(YRequestAttribute)}");
api = yandex;
storage = auth;
// Устройство по умолчанию
device = $"os=CSharp; os_version=; manufacturer=K1llM@n; model=Yandex Music API; clid=; device_id={storage.DeviceId}; uuid=random";
}
internal YRequest<ResponseType> Build(ParamsTuple tuple)
{
subs = GetSubstitutions(tuple);
HttpRequestMessage msg = CreateMessage(tuple);
return new YRequest<ResponseType>(msg, api, storage);
}
}
}