-
Notifications
You must be signed in to change notification settings - Fork 0
/
WalkmanLibUpdates.cs
158 lines (133 loc) · 7.65 KB
/
WalkmanLibUpdates.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
#if NETCOREAPP
using System.Text.Json;
#else
// add a reference to System.Web.Extensions
using System.Web.Script.Serialization;
#endif
public partial class WalkmanLib {
public struct VersionInfo {
/// <summary>Name of the tag.</summary>
public string TagName;
/// <summary>Title of the release.</summary>
public string Title;
/// <summary>Body of the release. Consists of raw release text, optionally parse it as markdown before displaying it.</summary>
public string Body;
}
/// <summary>Gets information about the latest release in a GitHub project.</summary>
/// <param name="projectName">Name of the project repository.</param>
/// <param name="projectOwner">Owner of the project repository. Default: Walkman100</param>
/// <returns>A <see cref="VersionInfo"/> object populated with information about the latest release.</returns>
public static VersionInfo GetLatestVersionInfo(string projectName, string projectOwner = "Walkman100") {
// https://stackoverflow.com/a/2904963/2999220
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
// https://stackoverflow.com/a/16655779/2999220
string address = string.Format("https://api.github.com/repos/{0}/{1}/releases/latest", projectOwner, projectName);
string jsonObject;
using (var client = new WebClient()) {
var frameworkInfo = new System.Runtime.Versioning.FrameworkName(AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName);
// https://stackoverflow.com/a/22134980/2999220
client.Headers.Add(HttpRequestHeader.UserAgent, $"{frameworkInfo.Identifier} v{frameworkInfo.Version}");
using (var reader = new StreamReader(client.OpenRead(address))) {
jsonObject = reader.ReadToEnd();
}
}
#if NETCOREAPP
Dictionary<string, object> jsonObjectDict = JsonSerializer.Deserialize<Dictionary<string, object>>(jsonObject);
#else
// https://stackoverflow.com/a/38944715/2999220
var jss = new JavaScriptSerializer();
Dictionary<string, object> jsonObjectDict = jss.Deserialize<Dictionary<string, object>>(jsonObject);
#endif
return new VersionInfo() {
TagName = (string)jsonObjectDict["tag_name"],
Title = (string)jsonObjectDict["name"],
Body = (string)jsonObjectDict["body"]
};
}
/// <summary>Gets a download link for the latest installer released in a GitHub project.</summary>
/// <param name="projectName">Name of the project repository.</param>
/// <param name="projectOwner">Owner of the project repository. Default: Walkman100</param>
/// <param name="fileName">Name of the file. Defaults to "<paramref name="projectName"/>-Installer.exe". Use {0} to replace with the version string.</param>
/// <returns>Download URI in a <see cref="string"/>.</returns>
public static string GetLatestDownloadLink(string projectName, string projectOwner = "Walkman100", string fileName = null) {
string versionString;
versionString = GetLatestVersionInfo(projectName, projectOwner).TagName;
if (fileName == null) {
fileName = projectName + "-Installer.exe";
} else {
fileName = string.Format(fileName, versionString);
}
return string.Format("https://github.com/{0}/{1}/releases/download/{2}/{3}", projectOwner, projectName, versionString, fileName);
}
/// <summary>Gets the latest version released in a GitHub project. Note if the tag name is not in version format will throw an Exception.</summary>
/// <param name="projectName">Name of the project repository.</param>
/// <param name="projectOwner">Owner of the project repository. Default: Walkman100</param>
/// <returns>The latest release version parsed as a <see cref="Version"/> object.</returns>
public static Version GetLatestVersion(string projectName, string projectOwner = "Walkman100") {
string versionString;
versionString = GetLatestVersionInfo(projectName, projectOwner).TagName;
if (versionString.StartsWith("v")) {
versionString = versionString.Substring(1);
}
return Version.Parse(versionString);
}
/// <summary>Checks if an update release is available in a GitHub project.</summary>
/// <param name="projectName">Name of the project repository.</param>
/// <param name="currentVersion"><see cref="Version"/> to check against.</param>
/// <param name="projectOwner">Owner of the project repository. Default: Walkman100</param>
/// <returns><see langword="true"/> if latest version is newer than <paramref name="currentVersion"/>, else <see langword="false"/>.</returns>
public static bool CheckIfUpdateAvailable(string projectName, Version currentVersion, string projectOwner = "Walkman100") {
Version latestVersion = GetLatestVersion(projectName, projectOwner);
return latestVersion > currentVersion;
}
/// <summary>Checks if an update release is available in a GitHub project in a BackgroundWorker.</summary>
/// <param name="projectName">Name of the project repository.</param>
/// <param name="currentVersion"><see cref="Version"/> to check against.</param>
/// <param name="checkComplete">Use "<c>[returnVoid]</c>" and put your return void in place of <c>returnVoid</c> (see Returns info).</param>
/// <param name="projectOwner">Owner of the project repository. Default: Walkman100</param>
/// <returns>
/// Create a Sub with the signature "<c>Object sender, ComponentModel.RunWorkerCompletedEventArgs e</c>", and within check <c>e.Error</c> for an exception before
/// using "<c>(bool)e.Result</c>": <see langword="true"/> if latest version is newer than <paramref name="currentVersion"/>, else <see langword="false"/>.
/// </returns>
public static void CheckIfUpdateAvailableInBackground(string projectName, Version currentVersion, System.ComponentModel.RunWorkerCompletedEventHandler checkComplete, string projectOwner = "Walkman100") {
var bwUpdateCheck = new System.ComponentModel.BackgroundWorker();
bwUpdateCheck.DoWork += BackgroundUpdateCheck;
bwUpdateCheck.RunWorkerCompleted += checkComplete;
bwUpdateCheck.RunWorkerAsync(new object[] {projectName, projectOwner, currentVersion});
}
private static void BackgroundUpdateCheck(object sender, System.ComponentModel.DoWorkEventArgs e) {
string projectName = (string)((object[])e.Argument)[0];
string projectOwner = (string)((object[])e.Argument)[1];
Version currentVersion = (Version)((object[])e.Argument)[2];
Version latestVersion;
int retries = 0;
while (true) {
try {
latestVersion = GetLatestVersion(projectName, projectOwner);
break;
} catch (WebException) {
retries += 1;
if (retries > 2) {
throw;
}
}
}
e.Result = latestVersion > currentVersion;
}
// Example code to use the background update check:
//void Main() {
// WalkmanLib.CheckIfUpdateAvailableInBackground(projectName, Application.ProductVersion, UpdateCheckReturn);
//}
//void UpdateCheckReturn(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) {
// if (e.Error == null) {
// Console.WriteLine("Update available: " + (bool)e.Result);
// } else {
// Console.WriteLine("Error checking for updates: " + e.Error.Message);
// }
//}
}