2020-07-31 02:12:14 +02:00
|
|
|
using System;
|
|
|
|
using System.Net.Http;
|
2020-08-01 15:38:09 +02:00
|
|
|
using System.Text.RegularExpressions;
|
2020-07-31 02:12:14 +02:00
|
|
|
using System.Threading;
|
|
|
|
using System.Threading.Tasks;
|
2020-08-01 16:10:05 +02:00
|
|
|
using BTCPayServer.Configuration;
|
2020-08-01 14:58:27 +02:00
|
|
|
using BTCPayServer.Logging;
|
2020-07-31 02:12:14 +02:00
|
|
|
using BTCPayServer.Services;
|
|
|
|
using BTCPayServer.Services.Notifications;
|
|
|
|
using BTCPayServer.Services.Notifications.Blobs;
|
2020-08-01 14:58:27 +02:00
|
|
|
using Microsoft.Extensions.Logging;
|
2020-07-31 02:12:14 +02:00
|
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
|
|
|
|
namespace BTCPayServer.HostedServices
|
|
|
|
{
|
|
|
|
public class NewVersionCheckerHostedService : BaseAsyncService
|
|
|
|
{
|
|
|
|
private readonly SettingsRepository _settingsRepository;
|
|
|
|
private readonly BTCPayServerEnvironment _env;
|
|
|
|
private readonly NotificationSender _notificationSender;
|
|
|
|
private readonly IVersionFetcher _versionFetcher;
|
|
|
|
|
|
|
|
public NewVersionCheckerHostedService(SettingsRepository settingsRepository, BTCPayServerEnvironment env,
|
|
|
|
NotificationSender notificationSender, IVersionFetcher versionFetcher)
|
|
|
|
{
|
|
|
|
_settingsRepository = settingsRepository;
|
|
|
|
_env = env;
|
|
|
|
_notificationSender = notificationSender;
|
|
|
|
_versionFetcher = versionFetcher;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal override Task[] InitializeTasks()
|
|
|
|
{
|
2020-07-31 03:44:37 +02:00
|
|
|
return new Task[] { CreateLoopTask(LoopVersionCheck) };
|
2020-07-31 02:12:14 +02:00
|
|
|
}
|
|
|
|
|
2020-07-31 03:44:37 +02:00
|
|
|
protected async Task LoopVersionCheck()
|
|
|
|
{
|
2020-08-01 14:58:27 +02:00
|
|
|
try
|
|
|
|
{
|
|
|
|
await ProcessVersionCheck();
|
|
|
|
}
|
|
|
|
catch (Exception ex)
|
|
|
|
{
|
|
|
|
Logs.Events.LogError(ex, "Error while performing new version check");
|
|
|
|
}
|
2020-07-31 03:44:37 +02:00
|
|
|
await Task.Delay(TimeSpan.FromDays(1), Cancellation);
|
|
|
|
}
|
|
|
|
|
|
|
|
public async Task ProcessVersionCheck()
|
2020-07-31 02:12:14 +02:00
|
|
|
{
|
|
|
|
var policies = await _settingsRepository.GetSettingAsync<PoliciesSettings>() ?? new PoliciesSettings();
|
2020-07-31 07:20:17 +02:00
|
|
|
if (policies.CheckForNewVersions)
|
2020-07-31 02:12:14 +02:00
|
|
|
{
|
|
|
|
var tag = await _versionFetcher.Fetch(Cancellation);
|
|
|
|
if (tag != null && tag != _env.Version)
|
|
|
|
{
|
|
|
|
var dh = await _settingsRepository.GetSettingAsync<NewVersionCheckerDataHolder>() ?? new NewVersionCheckerDataHolder();
|
|
|
|
if (dh.LastVersion != tag)
|
|
|
|
{
|
|
|
|
await _notificationSender.SendNotification(new AdminScope(), new NewVersionNotification(tag));
|
|
|
|
|
|
|
|
dh.LastVersion = tag;
|
|
|
|
await _settingsRepository.UpdateSetting(dh);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-07-31 03:44:37 +02:00
|
|
|
}
|
2020-07-31 02:12:14 +02:00
|
|
|
|
2020-07-31 03:44:37 +02:00
|
|
|
public class NewVersionCheckerDataHolder
|
|
|
|
{
|
|
|
|
public string LastVersion { get; set; }
|
|
|
|
}
|
|
|
|
|
|
|
|
public interface IVersionFetcher
|
|
|
|
{
|
|
|
|
Task<string> Fetch(CancellationToken cancellation);
|
|
|
|
}
|
2020-07-31 02:12:14 +02:00
|
|
|
|
2020-08-01 15:38:09 +02:00
|
|
|
public class GithubVersionFetcher : IVersionFetcher
|
2020-07-31 03:44:37 +02:00
|
|
|
{
|
|
|
|
private readonly HttpClient _httpClient;
|
2020-08-01 16:10:05 +02:00
|
|
|
private readonly Uri _updateurl;
|
|
|
|
public GithubVersionFetcher(IHttpClientFactory httpClientFactory, BTCPayServerOptions options)
|
2020-07-31 02:12:14 +02:00
|
|
|
{
|
2020-07-31 07:20:17 +02:00
|
|
|
_httpClient = httpClientFactory.CreateClient(nameof(GithubVersionFetcher));
|
2020-07-31 03:44:37 +02:00
|
|
|
_httpClient.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
|
|
|
|
_httpClient.DefaultRequestHeaders.Add("User-Agent", "BTCPayServer/NewVersionChecker");
|
2020-08-01 16:10:05 +02:00
|
|
|
|
|
|
|
_updateurl = options.UpdateUrl;
|
2020-07-31 02:12:14 +02:00
|
|
|
}
|
|
|
|
|
2020-08-01 15:38:09 +02:00
|
|
|
private static readonly Regex _releaseVersionTag = new Regex("^(v[1-9]+(\\.[0-9]+)*(-[0-9]+)?)$");
|
2020-07-31 03:44:37 +02:00
|
|
|
public async Task<string> Fetch(CancellationToken cancellation)
|
2020-07-31 02:12:14 +02:00
|
|
|
{
|
2020-08-03 10:16:29 +02:00
|
|
|
if (_updateurl == null)
|
|
|
|
return null;
|
|
|
|
|
2020-08-01 16:10:05 +02:00
|
|
|
using (var resp = await _httpClient.GetAsync(_updateurl, cancellation))
|
2020-07-31 02:12:14 +02:00
|
|
|
{
|
2020-08-01 14:58:27 +02:00
|
|
|
var strResp = await resp.Content.ReadAsStringAsync();
|
|
|
|
if (resp.IsSuccessStatusCode)
|
|
|
|
{
|
2020-08-01 15:38:09 +02:00
|
|
|
var jobj = JObject.Parse(strResp);
|
|
|
|
var tag = jobj["tag_name"].ToString();
|
|
|
|
|
|
|
|
var isReleaseVersionTag = _releaseVersionTag.IsMatch(tag);
|
2020-10-06 06:09:05 +02:00
|
|
|
if (isReleaseVersionTag)
|
|
|
|
{
|
|
|
|
return tag.TrimStart('v');
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
2020-08-01 14:58:27 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Logs.Events.LogWarning($"Unsuccessful status code returned during new version check. " +
|
2020-08-01 16:10:05 +02:00
|
|
|
$"Url: {_updateurl}, HTTP Code: {resp.StatusCode}, Response Body: {strResp}");
|
2020-08-01 14:58:27 +02:00
|
|
|
}
|
2020-07-31 02:12:14 +02:00
|
|
|
}
|
2020-07-31 03:44:37 +02:00
|
|
|
|
|
|
|
return null;
|
2020-07-31 02:12:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|