using System.Security.Cryptography;
using System.Text;
using YandexMusic.API.Common;
using YandexMusic.API.Models.Common;
using YandexMusic.API.Models.Track;
using YandexMusic.API.Requests.Track;
namespace YandexMusic.API
{
///
/// API для взаимодействия с треками
///
public partial class YTrackAPI : YCommonAPI
{
#region Вспомогательные функции
private string BuildLinkForDownload(YTrackDownloadInfo mainDownloadResponse, YStorageDownloadFile storageDownload)
{
string path = storageDownload.Path;
string host = storageDownload.Host;
string ts = storageDownload.Ts;
string s = storageDownload.S;
string codec = mainDownloadResponse.Codec;
string secret = $"XGRlBW9FXlekgbPrRHuSiA{path.Substring(1, path.Length - 1)}{s}";
MD5 md5 = MD5.Create();
byte[] md5Hash = md5.ComputeHash(Encoding.UTF8.GetBytes(secret));
HMACSHA1 hmacsha1 = new();
byte[] hmasha1Hash = hmacsha1.ComputeHash(md5Hash);
string sign = BitConverter.ToString(hmasha1Hash).Replace("-", "").ToLower();
string link = $"https://{host}/get-{codec}/{sign}/{ts}{path}";
return link;
}
#endregion Вспомогательные функции
public YTrackAPI(YandexMusicApi yandex) : base(yandex)
{
}
///
/// Получение треков
///
/// Хранилище
/// Идентификатор трека
///
public Task>> GetAsync(AuthStorage storage, string trackId)
{
return new YGetTracksBuilder(api, storage)
.Build(new[] { trackId })
.GetResponseAsync();
}
///
/// Получение треков
///
/// Хранилище
/// Идентификаторы треков
///
public Task>> GetAsync(AuthStorage storage, IEnumerable trackIds)
{
return new YGetTracksBuilder(api, storage)
.Build(trackIds)
.GetResponseAsync();
}
///
/// Получение метаданных для загрузки
///
/// Хранилище
/// Ключ трека в формате {идентифактор трека:идентификатор альбома}
/// Должен ли ответ содержать прямую ссылку на загрузку
///
public Task>> GetMetadataForDownloadAsync(AuthStorage storage, string trackKey, bool direct = false)
{
return new YTrackDownloadInfoBuilder(api, storage)
.Build((trackKey, direct))
.GetResponseAsync();
}
///
/// Получение метаданных для загрузки
///
/// Хранилище
/// Трек
/// Должен ли ответ содержать прямую ссылку на загрузку
///
public Task>> GetMetadataForDownloadAsync(AuthStorage storage, YTrack track, bool direct = false)
{
return GetMetadataForDownloadAsync(storage, track.GetKey().ToString(), direct);
}
///
/// Получение информации для формирования ссылки для загрузки
///
/// Хранилище
/// Метаданные для загрузки
///
public Task GetDownloadFileInfoAsync(AuthStorage storage, YTrackDownloadInfo metadataInfo)
{
return new YStorageDownloadFileBuilder(api, storage)
.Build(metadataInfo.DownloadInfoUrl)
.GetResponseAsync();
}
///
/// Получение ссылки для загрузки
///
/// Хранилище
/// Ключ трека в формате {идентификатор трека:идентификатор альбома}
///
public async Task GetFileLinkAsync(AuthStorage storage, string trackKey)
{
YResponse> meta = await GetMetadataForDownloadAsync(storage, trackKey);
YTrackDownloadInfo info = meta.Result
.OrderByDescending(i => i.BitrateInKbps)
.First(m => m.Codec == "mp3");
YStorageDownloadFile storageDownload = await GetDownloadFileInfoAsync(storage, info);
return BuildLinkForDownload(info, storageDownload);
}
///
/// Получение ссылки для загрузки
///
/// Хранилище
/// Трек
///
public Task GetFileLinkAsync(AuthStorage storage, YTrack track)
{
return GetFileLinkAsync(storage, track.GetKey().ToString());
}
///
/// Отправка текущего состояния прослушиваемого трека
/// Хранилище
/// Трек
/// Наименования клиента, с которого происходит прослушивание
/// Проигрывается ли трек с кеша
/// Уникальный идентификатор проигрывания
/// Уникальный идентификатор плейлиста, если таковой прослушивается
/// Сколько было всего воспроизведено трека в секундах
/// Окончательное значение воспроизведенных секунд
///
///
public Task SendPlayTrackInfoAsync(AuthStorage storage, YTrack track, string from, bool fromCache = false, string playId = "", string playlistId = "", double totalPlayedSeconds = 0, double endPositionSeconds = 0)
{
return new YSendTrackInfoBuilder(api, storage)
.Build((track, from, fromCache, playId, playlistId, totalPlayedSeconds, endPositionSeconds))
.GetResponseAsync();
}
#region GetSupplement
///
/// Получение дополнительной информации для трека
///
/// Хранилище
/// Идентификатор трека
///
public Task> GetSupplementAsync(AuthStorage storage, string trackId)
{
return new YGetTrackSupplementBuilder(api, storage)
.Build(trackId)
.GetResponseAsync();
}
///
/// Получение дополнительной информации для трека
///
/// Хранилище
/// Трек
///
public Task> GetSupplementAsync(AuthStorage storage, YTrack track)
{
return new YGetTrackSupplementBuilder(api, storage)
.Build(track.GetKey().ToString())
.GetResponseAsync();
}
#endregion GetSupplement
#region GetSimilar
///
/// Получение похожих треков
///
/// Хранилище
/// Идентификатор трека
///
public Task> GetSimilarAsync(AuthStorage storage, string trackId)
{
return new YGetTrackSimilarBuilder(api, storage)
.Build(trackId)
.GetResponseAsync();
}
///
/// Получение похожих треков
///
/// Хранилище
/// Трек
///
public Task> GetSimilarAsync(AuthStorage storage, YTrack track)
{
return new YGetTrackSimilarBuilder(api, storage)
.Build(track.GetKey().ToString())
.GetResponseAsync();
}
#endregion GetSimilar
#region Получение данных трека
#region В файл
///
/// Выгрузка в файл
///
/// Хранилище
/// Ключ трека в формате {идентификатор трека:идентификатор альбома}
/// Путь для файла
public async Task ExtractToFileAsync(AuthStorage storage, string trackKey, string filePath)
{
string url = await GetFileLinkAsync(storage, trackKey);
await new DataDownloader(storage).ToFile(url, filePath);
}
///
/// Выгрузка в файл
///
/// Хранилище
/// Трек
/// Путь для файла
public Task ExtractToFileAsync(AuthStorage storage, YTrack track, string filePath)
{
return ExtractToFileAsync(storage, track.GetKey().ToString(), filePath);
}
#endregion В файл
#region В массив байт
///
/// Получение двоичного массива данных
///
/// Хранилище
/// Ключ трека в формате {идентификатор трека:идентификатор альбома}
///
public async Task ExtractDataAsync(AuthStorage storage, string trackKey)
{
string url = await GetFileLinkAsync(storage, trackKey);
return await new DataDownloader(storage).AsBytes(url);
}
///
/// Получение двоичного массива данных
///
/// Хранилище
/// Трек
///
public Task ExtractDataAsync(AuthStorage storage, YTrack track)
{
return ExtractDataAsync(storage, track.GetKey().ToString());
}
#endregion В массив байт
#region В поток
///
/// Получение потока данных
///
/// Хранилище
/// Ключ трека в формате {идентификатор трека:идентификатор альбома}
/// Параметры передачи управления при http запросе
///
public async Task ExtractStreamAsync(AuthStorage storage, string trackKey,
HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead)
{
string url = await GetFileLinkAsync(storage, trackKey);
return await new DataDownloader(storage).AsStream(url, httpCompletionOption);
}
///
/// Получение потока данных
///
/// Хранилище
/// Трек
/// Параметры передачи управления при http запросе
///
public Task ExtractStreamAsync(AuthStorage storage, YTrack track,
HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead)
{
return ExtractStreamAsync(storage, track.GetKey().ToString(), httpCompletionOption);
}
#endregion В поток
#endregion Получение данных трека
}
}