rdt-client/server/RdtClient.Service/BackgroundServices/UpdateChecker.cs
2026-02-23 20:04:53 -07:00

102 lines
3.4 KiB
C#

using System.Reflection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace RdtClient.Service.BackgroundServices;
public class UpdateChecker(ILogger<UpdateChecker> logger, IHttpClientFactory httpClientFactory) : BackgroundService
{
private static readonly List<String> KnownGhsaIds = [];
public static String? CurrentVersion { get; private set; }
public static String? LatestVersion { get; private set; }
public static Boolean? IsInsecure { get; private set; }
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!Startup.Ready)
{
await Task.Delay(1000, stoppingToken);
}
var version = Assembly.GetEntryAssembly()?.GetName().Version?.ToString();
if (String.IsNullOrWhiteSpace(version))
{
CurrentVersion = "";
return;
}
CurrentVersion = $"v{version[..version.LastIndexOf('.')]}";
logger.LogInformation("UpdateChecker started, currently on version {CurrentVersion}.", CurrentVersion);
while (!stoppingToken.IsCancellationRequested)
{
try
{
var gitHubReleases = await GitHubRequest<List<GitHubReleasesResponse>>("/repos/rogerfar/rdt-client/tags?per_page=1", stoppingToken);
var latestRelease = gitHubReleases?.FirstOrDefault(m => m.Name != null)?.Name;
if (latestRelease == null)
{
logger.LogWarning($"Unable to find latest version on GitHub");
return;
}
if (latestRelease != CurrentVersion)
{
logger.LogInformation("New version found on GitHub: {latestRelease}", latestRelease);
}
LatestVersion = latestRelease;
var gitHubSecurityAdvisories = await GitHubRequest<List<GitHubSecurityAdvisoriesResponse>>("/repos/rogerfar/rdt-client/security-advisories", stoppingToken);
var unseenGhsaIds = gitHubSecurityAdvisories?.Where(advisory => !KnownGhsaIds.Contains(advisory.GhsaId));
if (unseenGhsaIds == null)
{
logger.LogWarning($"Unable to find security advisories on GitHub");
return;
}
IsInsecure = unseenGhsaIds.Any();
}
catch (Exception ex)
{
logger.LogDebug(ex, "Unexpected error occurred while checking for updates. This error is safe to ignore.");
}
await Task.Delay(TimeSpan.FromHours(1), stoppingToken);
}
logger.LogInformation("UpdateChecker stopped.");
}
private async Task<T?> GitHubRequest<T>(String endpoint, CancellationToken cancellationToken)
{
var httpClient = httpClientFactory.CreateClient();
httpClient.DefaultRequestHeaders.UserAgent.Add(new("RdtClient", CurrentVersion));
var response = await httpClient.GetStringAsync($"https://api.github.com{endpoint}", cancellationToken);
return JsonConvert.DeserializeObject<T>(response);
}
}
public class GitHubReleasesResponse
{
[JsonProperty("name")]
public String? Name { get; set; }
}
public class GitHubSecurityAdvisoriesResponse
{
[JsonProperty("ghsa_id")]
public required String GhsaId { get; set; }
}