/trunk/Winify/Gotify/GotifyConnection.cs |
@@ -4,7 +4,6 @@ |
using System.Net; |
using System.Net.Http; |
using System.Net.Http.Headers; |
using System.Net.Security; |
using System.Security.Authentication; |
using System.Security.Cryptography.X509Certificates; |
using System.Text; |
@@ -15,8 +14,6 @@ |
using Servers; |
using WebSocketSharp; |
using WebSocketSharp.Net; |
using static System.Windows.Forms.VisualStyles.VisualStyleElement.StartPanel; |
using Configuration = Configuration.Configuration; |
using ErrorEventArgs = WebSocketSharp.ErrorEventArgs; |
using NetworkCredential = System.Net.NetworkCredential; |
|
@@ -46,7 +43,8 @@ |
|
private readonly Uri _httpUri; |
private WebSocket _webSocketSharp; |
private readonly global::Configuration.Configuration _configuration; |
private readonly Configuration.Configuration _configuration; |
private Task _initTask; |
|
#endregion |
|
@@ -54,16 +52,15 @@ |
|
private GotifyConnection() |
{ |
|
} |
|
public GotifyConnection(Server server, global::Configuration.Configuration configuration) : this() |
public GotifyConnection(Server server, Configuration.Configuration configuration) : this() |
{ |
_server = server; |
_configuration = configuration; |
|
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; |
var httpClientHandler = new HttpClientHandler() |
var httpClientHandler = new HttpClientHandler |
{ |
// mono does not implement this |
//SslProtocols = SslProtocols.Tls12 |
@@ -71,23 +68,17 @@ |
|
_httpClient = new HttpClient(httpClientHandler); |
if (_configuration.IgnoreSelfSignedCertificates) |
{ |
httpClientHandler.ServerCertificateCustomValidationCallback = |
(httpRequestMessage, cert, cetChain, policyErrors) => true; |
} |
|
if (_configuration.Proxy.Enable) |
{ |
httpClientHandler.Proxy = new WebProxy(_configuration.Proxy.Url, false, new string[] { }, |
new NetworkCredential(_configuration.Proxy.Username, _configuration.Proxy.Password)); |
} |
|
_httpClient = new HttpClient(httpClientHandler); |
if (!string.IsNullOrEmpty(_server.Username) && !string.IsNullOrEmpty(_server.Password)) |
{ |
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", |
Convert.ToBase64String(Encoding.Default.GetBytes($"{_server.Username}:{_server.Password}"))); |
} |
|
if (!Uri.TryCreate(_server.Url, UriKind.Absolute, out _httpUri)) |
{ |
@@ -113,7 +104,8 @@ |
} |
catch (ArgumentException exception) |
{ |
Log.Error($"No WebSockets URL could be built from the provided URL {_server.Url} due to {exception.Message}"); |
Log.Error( |
$"No WebSockets URL could be built from the provided URL {_server.Url} due to {exception.Message}"); |
} |
|
_webSocketsUri = webSocketsUriBuilder.Uri; |
@@ -157,6 +149,11 @@ |
|
Connect(); |
|
if (_configuration.RetrievePastNotificationHours != 0) |
{ |
_initTask = RetrievePastMessages(_cancellationToken); |
} |
|
_runTask = Run(_cancellationToken); |
} |
|
@@ -166,20 +163,15 @@ |
_webSocketSharp.SslConfiguration = new ClientSslConfiguration(_webSocketsUri.Host, |
new X509CertificateCollection(new X509Certificate[] { }), SslProtocols.Tls12, false); |
if (_configuration.Proxy.Enable) |
{ |
_webSocketSharp.SetProxy(_configuration.Proxy.Url, _configuration.Proxy.Username, _configuration.Proxy.Password); |
} |
_webSocketSharp.SetProxy(_configuration.Proxy.Url, _configuration.Proxy.Username, |
_configuration.Proxy.Password); |
|
if (!string.IsNullOrEmpty(_server.Username) && !string.IsNullOrEmpty(_server.Password)) |
{ |
_webSocketSharp.SetCredentials(_server.Username, _server.Password, true); |
} |
|
if (_configuration.IgnoreSelfSignedCertificates) |
{ |
_webSocketSharp.SslConfiguration.ServerCertificateValidationCallback += |
(sender, certificate, chain, errors) => true; |
} |
|
_webSocketSharp.Log.Output = (logData, s) => |
{ |
@@ -190,13 +182,14 @@ |
_webSocketSharp.OnError += WebSocketSharp_OnError; |
_webSocketSharp.OnOpen += WebSocketSharp_OnOpen; |
_webSocketSharp.OnClose += WebSocketSharp_OnClose; |
|
|
_webSocketSharp.ConnectAsync(); |
} |
|
private void WebSocketSharp_OnClose(object sender, CloseEventArgs e) |
{ |
Log.Information($"WebSockets connection to server {_webSocketsUri.AbsoluteUri} closed with reason {e.Reason}"); |
Log.Information( |
$"WebSockets connection to server {_webSocketsUri.AbsoluteUri} closed with reason {e.Reason}"); |
} |
|
private void WebSocketSharp_OnOpen(object sender, EventArgs e) |
@@ -206,7 +199,9 @@ |
|
private async void WebSocketSharp_OnError(object sender, ErrorEventArgs e) |
{ |
Log.Error($"Connection to WebSockets server {_webSocketsUri.AbsoluteUri} terminated unexpectedly with message {e.Message}", e.Exception); |
Log.Error( |
$"Connection to WebSockets server {_webSocketsUri.AbsoluteUri} terminated unexpectedly with message {e.Message}", |
e.Exception); |
|
if (_cancellationToken.IsCancellationRequested) |
{ |
@@ -224,17 +219,17 @@ |
{ |
if (e.RawData.Length == 0) |
{ |
Log.Warning($"Empty message received from server"); |
Log.Warning("Empty message received from server"); |
return; |
} |
|
var message = Encoding.UTF8.GetString(e.RawData, 0, e.RawData.Length); |
|
GotifyNotification gotifyNotification; |
GotifyMessage gotifyNotification; |
|
try |
{ |
gotifyNotification = JsonConvert.DeserializeObject<GotifyNotification>(message); |
{ |
gotifyNotification = JsonConvert.DeserializeObject<GotifyMessage>(message); |
} |
catch (JsonSerializationException exception) |
{ |
@@ -251,15 +246,21 @@ |
|
gotifyNotification.Server = _server; |
|
if (!Uri.TryCreate(Path.Combine($"{_httpUri}", "application"), UriKind.Absolute, |
out var applicationUri)) |
var applicationUriBuilder = new UriBuilder(_httpUri); |
try |
{ |
Log.Warning($"Could not build an URI to an application"); |
applicationUriBuilder.Path = Path.Combine(applicationUriBuilder.Path, "application"); |
} |
catch (ArgumentException exception) |
{ |
Log.Warning("Could not build an URI to an application"); |
|
return; |
} |
|
using (var imageStream = |
await RetrieveGotifyApplicationImage(gotifyNotification.AppId, applicationUri, _cancellationToken)) |
await RetrieveGotifyApplicationImage(gotifyNotification.AppId, applicationUriBuilder.Uri, |
_cancellationToken)) |
{ |
if (imageStream == null) |
{ |
@@ -278,7 +279,9 @@ |
|
public void Stop() |
{ |
if (_cancellationTokenSource != null) _cancellationTokenSource.Cancel(); |
if (_cancellationTokenSource == null) return; |
|
_cancellationTokenSource.Cancel(); |
} |
|
#endregion |
@@ -285,6 +288,79 @@ |
|
#region Private Methods |
|
private async Task RetrievePastMessages(CancellationToken cancellationToken) |
{ |
var messageUriBuilder = new UriBuilder(_httpUri); |
foreach (var application in await RetrieveGotifyApplications(cancellationToken)) |
{ |
try |
{ |
messageUriBuilder.Path = Path.Combine(messageUriBuilder.Path, "application", $"{application.Id}", |
"message"); |
} |
catch (ArgumentException exception) |
{ |
Log.Error($"No application URL could be built for {_server.Url} due to {exception.Message}"); |
|
continue; |
} |
|
var messagesResponse = await _httpClient.GetAsync(messageUriBuilder.Uri, cancellationToken); |
|
|
var messages = await messagesResponse.Content.ReadAsStringAsync(); |
|
GotifyMessageQuery gotifyMessageQuery; |
try |
{ |
gotifyMessageQuery = |
JsonConvert.DeserializeObject<GotifyMessageQuery>(messages); |
} |
catch (JsonSerializationException exception) |
{ |
Log.Warning($"Could not deserialize the message response: {exception.Message}"); |
|
continue; |
} |
|
var applicationUriBuilder = new UriBuilder(_httpUri); |
try |
{ |
applicationUriBuilder.Path = Path.Combine(applicationUriBuilder.Path, "application"); |
} |
catch (ArgumentException exception) |
{ |
Log.Warning($"Could not build an URI to an application: {exception}"); |
|
return; |
} |
|
foreach (var message in gotifyMessageQuery.Messages) |
{ |
if (message.Date < DateTime.Now - TimeSpan.FromHours(_configuration.RetrievePastNotificationHours)) |
continue; |
|
message.Server = _server; |
|
using (var imageStream = |
await RetrieveGotifyApplicationImage(message.AppId, applicationUriBuilder.Uri, |
_cancellationToken)) |
{ |
if (imageStream == null) |
{ |
Log.Warning("Could not find any application image for notification"); |
return; |
} |
|
var image = Image.FromStream(imageStream); |
|
GotifyNotification?.Invoke(this, |
new GotifyNotificationEventArgs(message, image)); |
} |
} |
} |
} |
|
private async Task Run(CancellationToken cancellationToken) |
{ |
try |
@@ -294,7 +370,8 @@ |
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken); |
} while (!cancellationToken.IsCancellationRequested); |
} |
catch (Exception exception) when (exception is OperationCanceledException || exception is ObjectDisposedException) |
catch (Exception exception) when (exception is OperationCanceledException || |
exception is ObjectDisposedException) |
{ |
} |
catch (Exception exception) |
@@ -303,6 +380,38 @@ |
} |
} |
|
private async Task<GotifyApplication[]> RetrieveGotifyApplications(CancellationToken cancellationToken) |
{ |
var applicationsUriBuilder = new UriBuilder(_httpUri); |
try |
{ |
applicationsUriBuilder.Path = Path.Combine(applicationsUriBuilder.Path, "application"); |
} |
catch (ArgumentException exception) |
{ |
Log.Error($"No application URL could be built for {_server.Url} due to {exception}"); |
} |
|
var applicationsResponse = await _httpClient.GetAsync(applicationsUriBuilder.Uri, cancellationToken); |
|
var applications = await applicationsResponse.Content.ReadAsStringAsync(); |
|
GotifyApplication[] gotifyApplications; |
try |
{ |
gotifyApplications = |
JsonConvert.DeserializeObject<GotifyApplication[]>(applications); |
} |
catch (JsonSerializationException exception) |
{ |
Log.Warning($"Could not deserialize the list of applications from the server: {exception}"); |
|
return null; |
} |
|
return gotifyApplications; |
} |
|
private async Task<Stream> RetrieveGotifyApplicationImage(int appId, Uri applicationUri, |
CancellationToken cancellationToken) |
{ |
/trunk/Winify/Settings/SettingsForm.Designer.cs |
@@ -90,6 +90,11 @@ |
this.tableLayoutPanel9 = new System.Windows.Forms.TableLayoutPanel(); |
this.button5 = new System.Windows.Forms.Button(); |
this.button6 = new System.Windows.Forms.Button(); |
this.groupBox8 = new System.Windows.Forms.GroupBox(); |
this.tableLayoutPanel14 = new System.Windows.Forms.TableLayoutPanel(); |
this.label13 = new System.Windows.Forms.Label(); |
this.trackBar1 = new System.Windows.Forms.TrackBar(); |
this.textBox4 = new System.Windows.Forms.TextBox(); |
this.tabControl1.SuspendLayout(); |
this.tabPage2.SuspendLayout(); |
this.flowLayoutPanel2.SuspendLayout(); |
@@ -117,6 +122,9 @@ |
this.tableLayoutPanel12.SuspendLayout(); |
this.tableLayoutPanel8.SuspendLayout(); |
this.tableLayoutPanel9.SuspendLayout(); |
this.groupBox8.SuspendLayout(); |
this.tableLayoutPanel14.SuspendLayout(); |
((System.ComponentModel.ISupportInitialize)(this.trackBar1)).BeginInit(); |
this.SuspendLayout(); |
// |
// tabControl1 |
@@ -147,6 +155,7 @@ |
this.flowLayoutPanel2.Controls.Add(this.groupBox3); |
this.flowLayoutPanel2.Controls.Add(this.groupBox6); |
this.flowLayoutPanel2.Controls.Add(this.groupBox7); |
this.flowLayoutPanel2.Controls.Add(this.groupBox8); |
this.flowLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill; |
this.flowLayoutPanel2.Location = new System.Drawing.Point(0, 0); |
this.flowLayoutPanel2.Name = "flowLayoutPanel2"; |
@@ -834,6 +843,62 @@ |
this.button6.UseVisualStyleBackColor = true; |
this.button6.Click += new System.EventHandler(this.Button6_Click); |
// |
// groupBox8 |
// |
this.groupBox8.Controls.Add(this.tableLayoutPanel14); |
this.groupBox8.Location = new System.Drawing.Point(209, 62); |
this.groupBox8.Name = "groupBox8"; |
this.groupBox8.Size = new System.Drawing.Size(200, 78); |
this.groupBox8.TabIndex = 3; |
this.groupBox8.TabStop = false; |
this.groupBox8.Text = "Retrieve Past Notifications on Start"; |
// |
// tableLayoutPanel14 |
// |
this.tableLayoutPanel14.ColumnCount = 2; |
this.tableLayoutPanel14.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 22.16495F)); |
this.tableLayoutPanel14.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 77.83505F)); |
this.tableLayoutPanel14.Controls.Add(this.label13, 0, 0); |
this.tableLayoutPanel14.Controls.Add(this.trackBar1, 1, 0); |
this.tableLayoutPanel14.Controls.Add(this.textBox4, 1, 1); |
this.tableLayoutPanel14.Dock = System.Windows.Forms.DockStyle.Fill; |
this.tableLayoutPanel14.Location = new System.Drawing.Point(3, 16); |
this.tableLayoutPanel14.Name = "tableLayoutPanel14"; |
this.tableLayoutPanel14.RowCount = 2; |
this.tableLayoutPanel14.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); |
this.tableLayoutPanel14.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); |
this.tableLayoutPanel14.Size = new System.Drawing.Size(194, 59); |
this.tableLayoutPanel14.TabIndex = 0; |
// |
// label13 |
// |
this.label13.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); |
this.label13.AutoSize = true; |
this.label13.Location = new System.Drawing.Point(3, 13); |
this.label13.Name = "label13"; |
this.label13.Size = new System.Drawing.Size(37, 13); |
this.label13.TabIndex = 0; |
this.label13.Text = "Hours"; |
// |
// trackBar1 |
// |
this.trackBar1.Dock = System.Windows.Forms.DockStyle.Fill; |
this.trackBar1.Location = new System.Drawing.Point(46, 3); |
this.trackBar1.Maximum = 48; |
this.trackBar1.Name = "trackBar1"; |
this.trackBar1.Size = new System.Drawing.Size(145, 33); |
this.trackBar1.TabIndex = 1; |
this.trackBar1.ValueChanged += new System.EventHandler(this.trackBar1_ValueChanged); |
// |
// textBox4 |
// |
this.textBox4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right))); |
this.textBox4.Location = new System.Drawing.Point(46, 42); |
this.textBox4.Name = "textBox4"; |
this.textBox4.ReadOnly = true; |
this.textBox4.Size = new System.Drawing.Size(145, 20); |
this.textBox4.TabIndex = 2; |
// |
// SettingsForm |
// |
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); |
@@ -877,6 +942,10 @@ |
this.tableLayoutPanel12.PerformLayout(); |
this.tableLayoutPanel8.ResumeLayout(false); |
this.tableLayoutPanel9.ResumeLayout(false); |
this.groupBox8.ResumeLayout(false); |
this.tableLayoutPanel14.ResumeLayout(false); |
this.tableLayoutPanel14.PerformLayout(); |
((System.ComponentModel.ISupportInitialize)(this.trackBar1)).EndInit(); |
this.ResumeLayout(false); |
|
} |
@@ -943,5 +1012,10 @@ |
private System.Windows.Forms.NumericUpDown numericUpDown1; |
private System.Windows.Forms.Label label12; |
private System.Windows.Forms.CheckBox checkBox4; |
private System.Windows.Forms.GroupBox groupBox8; |
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel14; |
private System.Windows.Forms.Label label13; |
private System.Windows.Forms.TrackBar trackBar1; |
private System.Windows.Forms.TextBox textBox4; |
} |
} |