85 lines
3.4 KiB
C#
85 lines
3.4 KiB
C#
using System.Net.Http.Headers;
|
||
using System.Text.Json;
|
||
|
||
namespace ReleaseUpdater;
|
||
|
||
/// <summary>
|
||
/// Провайдер для получения информации о релизах из Github / Gitea API.
|
||
/// </summary>
|
||
public sealed class ReleaseProvider
|
||
{
|
||
private static readonly JsonSerializerOptions JsonOpts = new(JsonSerializerDefaults.Web);
|
||
|
||
/// <summary>
|
||
/// Получает список всех релизов из указанного API.
|
||
/// </summary>
|
||
/// <param name="apiUrl">URL API Gitea для релизов.</param>
|
||
/// <param name="token">Токен авторизации (если требуется).</param>
|
||
/// <returns>Список релизов.</returns>
|
||
|
||
public async Task<IReadOnlyList<ReleaseInfo>> GetReleasesAsync(Uri apiUrl, string? token = null)
|
||
{
|
||
using var client = CreateClient(token);
|
||
using var resp = await client.GetAsync(apiUrl);
|
||
resp.EnsureSuccessStatusCode();
|
||
|
||
var stream = await resp.Content.ReadAsStreamAsync();
|
||
var releases = await JsonSerializer.DeserializeAsync<List<GiteaReleaseDto>>(stream, JsonOpts)
|
||
?? new List<GiteaReleaseDto>();
|
||
|
||
return releases.Select(Map).ToList();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Находит релиз по версии или возвращает последний релиз.
|
||
/// </summary>
|
||
/// <param name="apiUrl">URL API Gitea для релизов.</param>
|
||
/// <param name="versionOrLatest">Версия (например, "3.5.2") или "latest".</param>
|
||
/// <param name="token">Токен авторизации (если требуется).</param>
|
||
/// <returns>Информация о релизе или null.</returns>
|
||
|
||
public async Task<ReleaseInfo?> FindReleaseAsync(Uri apiUrl, string? versionOrLatest, string? token = null)
|
||
{
|
||
var all = await GetReleasesAsync(apiUrl, token);
|
||
if (string.IsNullOrWhiteSpace(versionOrLatest) || versionOrLatest.Equals("latest", StringComparison.OrdinalIgnoreCase))
|
||
return all.FirstOrDefault();
|
||
|
||
var tag = versionOrLatest.StartsWith('v') ? versionOrLatest : $"v{versionOrLatest}";
|
||
return all.FirstOrDefault(r => string.Equals(r.TagName, tag, StringComparison.OrdinalIgnoreCase));
|
||
}
|
||
|
||
private static HttpClient CreateClient(string? token)
|
||
{
|
||
var client = new HttpClient();
|
||
client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("ReleaseUpdater", "1.0"));
|
||
if (!string.IsNullOrWhiteSpace(token))
|
||
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("token", token);
|
||
return client;
|
||
}
|
||
|
||
private static ReleaseInfo Map(GiteaReleaseDto dto) =>
|
||
new()
|
||
{
|
||
TagName = dto.tag_name,
|
||
Name = dto.name,
|
||
Assets = dto.assets?.Select(a => new AssetInfo
|
||
{
|
||
Name = a.name,
|
||
DownloadUrl = new Uri(a.browser_download_url)
|
||
}).ToList() ?? new List<AssetInfo>()
|
||
};
|
||
|
||
// DTOs для десериализации JSON
|
||
private sealed class GiteaReleaseDto
|
||
{
|
||
public string tag_name { get; set; } = "";
|
||
public string? name { get; set; }
|
||
public List<GiteaAssetDto>? assets { get; set; }
|
||
}
|
||
|
||
private sealed class GiteaAssetDto
|
||
{
|
||
public string name { get; set; } = "";
|
||
public string browser_download_url { get; set; } = "";
|
||
}
|
||
} |