Skip to content

Commit

Permalink
feat: version checks (nuget & github)
Browse files Browse the repository at this point in the history
  • Loading branch information
Lulalaby committed Dec 21, 2023
1 parent 4024de2 commit fb57752
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 15 deletions.
2 changes: 1 addition & 1 deletion DisCatSharp/Clients/DiscordClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ public async Task ConnectAsync(DiscordActivity activity = null, UserStatus? stat
}

if (!this.Configuration.DisableUpdateCheck)
await Utilities.CheckVersionAsync(this, true, this.IsShard);
await Utilities.CheckGitHubVersionAsync(this, true, this.IsShard);

while (i-- > 0 || this.Configuration.ReconnectIndefinitely)
try
Expand Down
2 changes: 2 additions & 0 deletions DisCatSharp/DisCatSharp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ Written with love and for everyone.
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NuGet.Protocol" Version="6.8.0" />
<PackageReference Include="Octokit" Version="9.0.0" />
<PackageReference Include="Sentry" Version="3.41.3" />
<PackageReference Include="Sentry.Extensions.Logging" Version="3.41.3" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.1" />
Expand Down
88 changes: 74 additions & 14 deletions DisCatSharp/Utilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,27 @@
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;

using DisCatSharp.Attributes;
using DisCatSharp.Entities;
using DisCatSharp.Entities.DCS;
using DisCatSharp.Enums;
using DisCatSharp.Net;

using Microsoft.Extensions.Logging;

using Newtonsoft.Json;
using NuGet.Common;
using NuGet.Protocol;
using NuGet.Protocol.Core.Types;
using NuGet.Versioning;

using Octokit;
using Octokit.Internal;

using ILogger = Microsoft.Extensions.Logging.ILogger;
using LogLevel = Microsoft.Extensions.Logging.LogLevel;
using Repository = NuGet.Protocol.Core.Types.Repository;

namespace DisCatSharp;

Expand Down Expand Up @@ -480,8 +490,27 @@ internal static void Deconstruct<TKey, TValue>(this KeyValuePair<TKey, TValue> k
/// Perfoms a version check against github releases.
/// </summary>
/// <param name="client">The base discord client.</param>
public static Task CheckVersionAsync(DiscordClient client)
=> CheckVersionAsync(client, false);
/// <param name="owner">The owner of the target github <paramref name="repository"/>.</param>
/// <param name="repository">The target github repository.</param>
/// <param name="productName">The name of the product.</param>
/// <param name="manualVersion">The manual version string to check.</param>
/// <param name="githubToken">The token to use for private repositories.</param>
public static Task CheckGitHubVersionAsync(DiscordClient client, string owner = "Aiko-IT-Systems", string repository = "DisCatSharp", string productName = "DisCatSharp", string? manualVersion = null, string? githubToken = null)
=> CheckGitHubVersionAsync(client, false, false, owner, repository, productName, manualVersion, githubToken);

/// <summary>
/// Perfoms a version check against github releases.
/// </summary>
/// <param name="client">The base discord client.</param>
/// <param name="startupCheck">Whether this is called on startup.</param>
/// <param name="fromShard">Whether this method got called from a sharded client.</param>
/// <param name="owner">The owner of the target github <paramref name="repository"/>.</param>
/// <param name="repository">The target github repository.</param>
/// <param name="productName">The name of the product.</param>
/// <param name="manualVersion">The manual version string to check.</param>
/// <param name="githubToken">The token to use for private repositories.</param>
internal static Task CheckVersionAsync(BaseDiscordClient client, bool startupCheck, bool fromShard = false, string owner = "Aiko-IT-Systems", string repository = "DisCatSharp", string productName = "DisCatSharp", string? manualVersion = null, string? githubToken = null)
=> CheckGitHubVersionAsync(client, startupCheck, fromShard, owner, repository, productName, manualVersion, githubToken);

/// <summary>
/// Perfoms a version check against github releases.
Expand All @@ -494,7 +523,7 @@ public static Task CheckVersionAsync(DiscordClient client)
/// <param name="productName">The name of the product.</param>
/// <param name="manualVersion">The manual version string to check.</param>
/// <param name="githubToken">The token to use for private repositories.</param>
internal static async Task CheckVersionAsync(BaseDiscordClient client, bool startupCheck, bool fromShard = false, string owner = "Aiko-IT-Systems", string repository = "DisCatSharp", string productName = "DisCatSharp", string? manualVersion = null, string? githubToken = null)
internal static async Task CheckGitHubVersionAsync(BaseDiscordClient client, bool startupCheck, bool fromShard = false, string owner = "Aiko-IT-Systems", string repository = "DisCatSharp", string productName = "DisCatSharp", string? manualVersion = null, string? githubToken = null)
{
if (startupCheck && VersionCheckFinishedFor.TryGetValue(productName, out var val) && val && manualVersion is null)
return;
Expand All @@ -507,20 +536,18 @@ internal static async Task CheckVersionAsync(BaseDiscordClient client, bool star
var api = Convert.ToInt32(splitVersion[0]);
var major = Convert.ToInt32(splitVersion[1]);
var minor = Convert.ToInt32(splitVersion[2]);
if (githubToken is not null)
client.RestClient.DefaultRequestHeaders.Authorization = new("token", githubToken);

var res = await client.RestClient.GetStringAsync($"https://api.github.com/repos/{owner}/{repository}/releases?per_page=1");
ApiConnection apiConnection = githubToken is not null ? new(new Connection(new($"{client.BotLibrary}", client.VersionString), new InMemoryCredentialStore(new(githubToken)))) : new(new Connection(new($"{client.BotLibrary}", client.VersionString)));
ReleasesClient releaseClient = new(apiConnection);
var latest = await releaseClient.GetLatest(owner, repository);

if (string.IsNullOrEmpty(res))
if (latest is null)
{
client.Logger.LogWarning("[{Type}] Failed to check for updates. Could not determine remote version", fromShard ? "ShardedClient" : "Client");
return;
}

var releaseInformations = JsonConvert.DeserializeObject<List<GitHubRelease>>(res)!;
var targetLastRelease = releaseInformations.First();
var lastGitHubRelease = targetLastRelease.TagName.Replace("v", string.Empty, StringComparison.InvariantCultureIgnoreCase);
var lastGitHubRelease = latest.TagName.Replace("v", string.Empty, StringComparison.InvariantCultureIgnoreCase);
var githubSplitVersion = lastGitHubRelease.Split('.');
var githubApi = Convert.ToInt32(githubSplitVersion[0]);
var githubMajor = Convert.ToInt32(githubSplitVersion[1]);
Expand All @@ -542,8 +569,41 @@ internal static async Task CheckVersionAsync(BaseDiscordClient client, bool star
if (startupCheck)
if (!VersionCheckFinishedFor.TryAdd(productName, true) && VersionCheckFinishedFor.TryGetValue(productName, out _))
VersionCheckFinishedFor[productName] = true;
if (githubToken is not null)
client.RestClient.DefaultRequestHeaders.Authorization = null;
}
}

/// <summary>
/// Performs a version check against nuget.
/// </summary>
/// <param name="client">The base discord client.</param>
/// <param name="packageId">The id of the package.</param>
/// <param name="manualVersion">The manual version string to check.</param>
/// <returns></returns>
public static async Task CheckNuGetVersionAsync(BaseDiscordClient client, string packageId = "DisCatSharp", string? manualVersion = null, bool includePrerelease = true)
{
var repository = Repository.Factory.GetCoreV3("https://api.nuget.org/v3/index.json");
var resource = await repository.GetResourceAsync<MetadataResource>();
var sourceCache = new SourceCacheContext()
{
RefreshMemoryCache = true,
IgnoreFailedSources = true,
NoCache = true
};
var latestVersions = (await resource.GetLatestVersions(new List<string>()
{
packageId.ToLowerInvariant()
}, includePrerelease, false, sourceCache, new NullLogger(), CancellationToken.None))?.ToList() ?? throw new("Could not get latest versions");

var latestPackageVersion = latestVersions.First(x => string.Equals(x.Key, packageId, StringComparison.InvariantCultureIgnoreCase)).Value;
var version = manualVersion ?? client.VersionString;
var gitLessVersion = version.Split('+')[0];

NuGetVersion currentPackageVersion = new(gitLessVersion);
if (latestPackageVersion > currentPackageVersion)
client.Logger.LogCritical("Your version of {Product} is outdated!\n\tCurrent version: v{CurrentVersion}\n\tLatest version: v{LastGitHubRelease}", packageId, currentPackageVersion.OriginalVersion, latestPackageVersion.OriginalVersion);
else if (latestPackageVersion < currentPackageVersion)
client.Logger.LogWarning("Your version of {Product} is newer than the latest release!\n\tPre-release are not recommended for production.\n\tCurrent version: v{CurrentVersion}\n\tLatest version: v{LastGitHubRelease}", packageId, currentPackageVersion.OriginalVersion, latestPackageVersion.OriginalVersion);
else
client.Logger.LogInformation("Your version of {Product} is up to date!\n\tCurrent version: v{CurrentVersion}", packageId, currentPackageVersion.OriginalVersion);
}
}

0 comments on commit fb57752

Please sign in to comment.