diff --git a/.semver.txt b/.semver.txt
index 5b09c67..a970716 100644
--- a/.semver.txt
+++ b/.semver.txt
@@ -1 +1 @@
-1.0.14
+1.0.15
diff --git a/src/JiraTimeBot/JiraTimeBot.csproj b/src/JiraTimeBot/JiraTimeBot.csproj
index ad5b4cf..c59fa35 100644
--- a/src/JiraTimeBot/JiraTimeBot.csproj
+++ b/src/JiraTimeBot/JiraTimeBot.csproj
@@ -118,6 +118,8 @@
+
+
frmMain.cs
diff --git a/src/JiraTimeBot/Properties/AssemblyInfo.cs b/src/JiraTimeBot/Properties/AssemblyInfo.cs
index 69a93e1..6639964 100644
--- a/src/JiraTimeBot/Properties/AssemblyInfo.cs
+++ b/src/JiraTimeBot/Properties/AssemblyInfo.cs
@@ -1,31 +1,31 @@
-using System.Reflection;
-using System.Runtime.InteropServices;
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("JiraTimeBot")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("JiraTimeBot")]
-[assembly: AssemblyCopyright("Copyright © 2019")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("f3b89316-c38c-4ce6-9d88-0b1373cfba1a")]
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-[assembly: AssemblyVersion("1.0.14")]
-[assembly: AssemblyFileVersion("1.0.14")]
-[assembly: AssemblyInformationalVersion("1.0.14")]
+using System.Reflection;
+using System.Runtime.InteropServices;
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("JiraTimeBot")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("JiraTimeBot")]
+[assembly: AssemblyCopyright("Copyright © 2019")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("f3b89316-c38c-4ce6-9d88-0b1373cfba1a")]
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+[assembly: AssemblyVersion("1.0.15")]
+[assembly: AssemblyFileVersion("1.0.15")]
+[assembly: AssemblyInformationalVersion("1.0.15")]
diff --git a/src/JiraTimeBot/UI/frmMain.Designer.cs b/src/JiraTimeBot/UI/frmMain.Designer.cs
index 7adc607..fa52b07 100644
--- a/src/JiraTimeBot/UI/frmMain.Designer.cs
+++ b/src/JiraTimeBot/UI/frmMain.Designer.cs
@@ -38,6 +38,7 @@
this.btnMeeting = new System.Windows.Forms.Button();
this.btnCancel = new System.Windows.Forms.Button();
this.btnSettings = new System.Windows.Forms.Button();
+ this.tmrUpdate = new System.Windows.Forms.Timer(this.components);
this.SuspendLayout();
//
// txtLog
@@ -111,6 +112,11 @@
this.btnSettings.UseVisualStyleBackColor = true;
this.btnSettings.Click += new System.EventHandler(this.btnSettings_Click);
//
+ // tmrUpdate
+ //
+ this.tmrUpdate.Interval = 1000;
+ this.tmrUpdate.Tick += new System.EventHandler(this.tmrUpdate_Tick);
+ //
// frmMain
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@@ -144,6 +150,7 @@
private System.Windows.Forms.Button btnMeeting;
private System.Windows.Forms.Button btnCancel;
private System.Windows.Forms.Button btnSettings;
+ private System.Windows.Forms.Timer tmrUpdate;
}
}
diff --git a/src/JiraTimeBot/UI/frmMain.cs b/src/JiraTimeBot/UI/frmMain.cs
index 9a7d770..055a8f1 100644
--- a/src/JiraTimeBot/UI/frmMain.cs
+++ b/src/JiraTimeBot/UI/frmMain.cs
@@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
-using System.Net.Configuration;
+using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
@@ -9,6 +9,7 @@ using JiraTimeBotForm.Configuration;
using JiraTimeBotForm.DI;
using JiraTimeBotForm.TasksProcessors;
using JiraTimeBotForm.UI.Tray;
+using JiraTimeBotForm.Update;
// This is the code for your desktop app.
// Press Ctrl+F5 (or go to Debug > Start Without Debugging) to run your app.
@@ -90,8 +91,11 @@ namespace JiraTimeBotForm.UI
private void Form1_Load(object sender, EventArgs e)
{
+ this.Text = this.Text + " v." + Application.ProductVersion;
+
PrintStartMessage();
tmrStart.Enabled = true;
+ tmrUpdate.Enabled = true;
}
private void PrintStartMessage()
@@ -182,5 +186,27 @@ namespace JiraTimeBotForm.UI
PrintStartMessage();
}
+
+ private void tmrUpdate_Tick(object sender, EventArgs e)
+ {
+ tmrUpdate.Interval = 8 * 60 * 60 * 1000;
+
+ var checker = new UpdateChecker();
+ var release = checker.GetRelease();
+ if (release == null)
+ {
+ return;
+ }
+
+ var gitVersionStr = checker.GetLatestVersion(release);
+ var gitVersion = new Version(gitVersionStr);
+ var appVersion = new Version(Application.ProductVersion);
+
+ if (gitVersion > appVersion)
+ {
+ var downloadUrl = checker.GetDownloadUrl(release);
+ _log.Info($"Доступна новая версия: {gitVersion} {downloadUrl}");
+ }
+ }
}
}
diff --git a/src/JiraTimeBot/UI/frmMain.resx b/src/JiraTimeBot/UI/frmMain.resx
index 0fa7589..e075404 100644
--- a/src/JiraTimeBot/UI/frmMain.resx
+++ b/src/JiraTimeBot/UI/frmMain.resx
@@ -123,6 +123,9 @@
113, 17
+
+ 209, 17
+
diff --git a/src/JiraTimeBot/Update/GitHubDataObjects.cs b/src/JiraTimeBot/Update/GitHubDataObjects.cs
new file mode 100644
index 0000000..e7710d5
--- /dev/null
+++ b/src/JiraTimeBot/Update/GitHubDataObjects.cs
@@ -0,0 +1,167 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
+
+namespace JiraTimeBotForm.Update
+{
+ public partial class GitHubReleaseResponse
+ {
+ [JsonProperty("url")]
+ public Uri Url { get; set; }
+
+ [JsonProperty("assets_url")]
+ public Uri AssetsUrl { get; set; }
+
+ [JsonProperty("upload_url")]
+ public string UploadUrl { get; set; }
+
+ [JsonProperty("html_url")]
+ public Uri HtmlUrl { get; set; }
+
+ [JsonProperty("id")]
+ public long Id { get; set; }
+
+ [JsonProperty("node_id")]
+ public string NodeId { get; set; }
+
+ [JsonProperty("tag_name")]
+ public string TagName { get; set; }
+
+ [JsonProperty("target_commitish")]
+ public string TargetCommitish { get; set; }
+
+ [JsonProperty("name")]
+ public object Name { get; set; }
+
+ [JsonProperty("draft")]
+ public bool Draft { get; set; }
+
+ [JsonProperty("author")]
+ public Author Author { get; set; }
+
+ [JsonProperty("prerelease")]
+ public bool Prerelease { get; set; }
+
+ [JsonProperty("created_at")]
+ public DateTimeOffset CreatedAt { get; set; }
+
+ [JsonProperty("published_at")]
+ public DateTimeOffset PublishedAt { get; set; }
+
+ [JsonProperty("assets")]
+ public Asset[] Assets { get; set; }
+
+ [JsonProperty("tarball_url")]
+ public Uri TarballUrl { get; set; }
+
+ [JsonProperty("zipball_url")]
+ public Uri ZipballUrl { get; set; }
+
+ [JsonProperty("body")]
+ public object Body { get; set; }
+ }
+
+ public partial class Asset
+ {
+ [JsonProperty("url")]
+ public Uri Url { get; set; }
+
+ [JsonProperty("id")]
+ public long Id { get; set; }
+
+ [JsonProperty("node_id")]
+ public string NodeId { get; set; }
+
+ [JsonProperty("name")]
+ public string Name { get; set; }
+
+ [JsonProperty("label")]
+ public string Label { get; set; }
+
+ [JsonProperty("uploader")]
+ public Author Uploader { get; set; }
+
+ [JsonProperty("content_type")]
+ public string ContentType { get; set; }
+
+ [JsonProperty("state")]
+ public string State { get; set; }
+
+ [JsonProperty("size")]
+ public long Size { get; set; }
+
+ [JsonProperty("download_count")]
+ public long DownloadCount { get; set; }
+
+ [JsonProperty("created_at")]
+ public DateTimeOffset CreatedAt { get; set; }
+
+ [JsonProperty("updated_at")]
+ public DateTimeOffset UpdatedAt { get; set; }
+
+ [JsonProperty("browser_download_url")]
+ public Uri BrowserDownloadUrl { get; set; }
+ }
+
+ public partial class Author
+ {
+ [JsonProperty("login")]
+ public string Login { get; set; }
+
+ [JsonProperty("id")]
+ public long Id { get; set; }
+
+ [JsonProperty("node_id")]
+ public string NodeId { get; set; }
+
+ [JsonProperty("avatar_url")]
+ public Uri AvatarUrl { get; set; }
+
+ [JsonProperty("gravatar_id")]
+ public string GravatarId { get; set; }
+
+ [JsonProperty("url")]
+ public Uri Url { get; set; }
+
+ [JsonProperty("html_url")]
+ public Uri HtmlUrl { get; set; }
+
+ [JsonProperty("followers_url")]
+ public Uri FollowersUrl { get; set; }
+
+ [JsonProperty("following_url")]
+ public string FollowingUrl { get; set; }
+
+ [JsonProperty("gists_url")]
+ public string GistsUrl { get; set; }
+
+ [JsonProperty("starred_url")]
+ public string StarredUrl { get; set; }
+
+ [JsonProperty("subscriptions_url")]
+ public Uri SubscriptionsUrl { get; set; }
+
+ [JsonProperty("organizations_url")]
+ public Uri OrganizationsUrl { get; set; }
+
+ [JsonProperty("repos_url")]
+ public Uri ReposUrl { get; set; }
+
+ [JsonProperty("events_url")]
+ public string EventsUrl { get; set; }
+
+ [JsonProperty("received_events_url")]
+ public Uri ReceivedEventsUrl { get; set; }
+
+ [JsonProperty("type")]
+ public string Type { get; set; }
+
+ [JsonProperty("site_admin")]
+ public bool SiteAdmin { get; set; }
+ }
+}
diff --git a/src/JiraTimeBot/Update/UpdateChecker.cs b/src/JiraTimeBot/Update/UpdateChecker.cs
new file mode 100644
index 0000000..a559f97
--- /dev/null
+++ b/src/JiraTimeBot/Update/UpdateChecker.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+
+namespace JiraTimeBotForm.Update
+{
+ class UpdateChecker
+ {
+ private const string GithubUser = "monster1025";
+ private const string GithubRepo = "JiraTimeBot";
+
+ public string GetLatestVersion(GitHubReleaseResponse release)
+ {
+ var version = release?.TagName?.TrimStart('v');
+ return version;
+ }
+
+ public string GetDownloadUrl(GitHubReleaseResponse release)
+ {
+ var downloadUrl = release?.Assets?.FirstOrDefault()?.BrowserDownloadUrl?.ToString();
+ return downloadUrl ?? "";
+ }
+
+ public GitHubReleaseResponse GetRelease()
+ {
+ var latestReleasePage = Get($"https://api.github.com/repos/{GithubUser}/{GithubRepo}/releases/latest");
+ if (string.IsNullOrEmpty(latestReleasePage))
+ {
+ return null;
+ }
+
+ var release = JsonConvert.DeserializeObject(latestReleasePage);
+ return release;
+ }
+
+ public void DownloadFile(string url)
+ {
+ using (var client = new WebClient())
+ {
+ client.Headers.Add("User-Agent", "Mozilla/5.0 (X11; Linux i686; rv:64.0) Gecko/20100101 Firefox/64.0");
+ client.DownloadFile(url, "update.zip");
+ }
+ }
+
+ private string Get(string uri)
+ {
+ try
+ {
+ HttpWebRequest request = (HttpWebRequest) WebRequest.Create(uri);
+ request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
+ request.UserAgent = "Mozilla/5.0 (X11; Linux i686; rv:64.0) Gecko/20100101 Firefox/64.0";
+
+ using (HttpWebResponse response = (HttpWebResponse) request.GetResponse())
+ using (Stream stream = response.GetResponseStream())
+ using (StreamReader reader = new StreamReader(stream))
+ {
+ return reader.ReadToEnd();
+ }
+ }
+ catch (Exception ex)
+ {
+ return "";
+ }
+ }
+ }
+}