Winify

Subversion Repositories:
Compare Path: Rev
With Path: Rev
?path1? @ 58  →  ?path2? @ 59
File deleted
\ No newline at end of file
/trunk/Winify/Gotify/GotifyNotification.cs
/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/Gotify/GotifyMessage.cs
@@ -0,0 +1,33 @@
using System;
using Newtonsoft.Json;
using Servers;
 
namespace Winify.Gotify
{
/// <summary>
/// {"id":22,"appid":1,"message":"iot","title":"Arcade
/// Netplay","priority":0,"date":"2022-10-26T14:55:59.050734643+03:00"}
/// </summary>
public class GotifyMessage
{
#region Public Enums, Properties and Fields
 
[JsonProperty(PropertyName = "id")] public int Id { get; set; }
 
[JsonProperty(PropertyName = "appid")] public int AppId { get; set; }
 
[JsonProperty(PropertyName = "message")]
public string Message { get; set; }
 
[JsonProperty(PropertyName = "title")] public string Title { get; set; }
 
[JsonProperty(PropertyName = "priority")]
public int Priority { get; set; }
 
[JsonProperty(PropertyName = "date")] public DateTime Date { get; set; }
 
[JsonIgnore] public Server Server { get; set; }
 
#endregion
}
}
/trunk/Winify/Gotify/GotifyMessageQuery.cs
@@ -0,0 +1,48 @@
using Newtonsoft.Json;
using Servers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace Winify.Gotify
{
/// <summary>
/// {
/// "paging":{
/// "size":2,
/// "since":0,
/// "limit":100
/// },
/// "messages":[
/// {
/// "id":26622,
/// "appid":1,
/// "message":"bbbb",
/// "title":"aaaa",
/// "priority":0,
/// "date":"2023-07-29T06:54:45.982069186Z"
/// },
/// {
/// "id":26621,
/// "appid":1,
/// "message":"bbbb",
/// "title":"aaaa",
/// "priority":0,
/// "date":"2023-07-29T06:48:29.397144801Z"
/// }
/// ]
/// }
/// </summary>
public class GotifyMessageQuery
{
#region Public Enums, Properties and Fields
 
[JsonProperty(PropertyName = "paging")] public GotifyPaging Paging { get; set; }
 
[JsonProperty(PropertyName = "messages")] public GotifyMessage[] Messages { get; set; }
 
#endregion
}
}
/trunk/Winify/Gotify/GotifyNotificationEventArgs.cs
@@ -7,7 +7,7 @@
{
#region Constructors, Destructors and Finalizers
 
public GotifyNotificationEventArgs(GotifyNotification notification, Image image)
public GotifyNotificationEventArgs(GotifyMessage notification, Image image)
{
Notification = notification;
Image = image;
@@ -17,7 +17,7 @@
 
#region Public Enums, Properties and Fields
 
public GotifyNotification Notification { get; set; }
public GotifyMessage Notification { get; set; }
 
public Image Image { get; set; }
 
/trunk/Winify/Gotify/GotifyPaging.cs
@@ -0,0 +1,19 @@
using Newtonsoft.Json;
using Servers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace Winify.Gotify
{
public class GotifyPaging
{
[JsonProperty(PropertyName = "size")] public int Size { get; set; }
 
[JsonProperty(PropertyName = "since")] public int Since { get; set; }
 
[JsonProperty(PropertyName = "limit")] public int Limit { get; set; }
}
}
/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;
}
}
/trunk/Winify/Settings/SettingsForm.cs
@@ -227,6 +227,14 @@
private void SettingsForm_Load(object sender, EventArgs e)
{
// Databindings.
trackBar1.DataBindings.Add(new Binding("Value", _configurationBindingSource,
nameof(_mainForm.Configuration.RetrievePastNotificationHours), true,
DataSourceUpdateMode.OnPropertyChanged));
 
textBox4.DataBindings.Add(new Binding("Text", _configurationBindingSource,
nameof(_mainForm.Configuration.RetrievePastNotificationHours), true,
DataSourceUpdateMode.OnPropertyChanged));
 
numericUpDown1.DataBindings.Add(new Binding("Value", _configurationBindingSource,
nameof(_mainForm.Configuration.ToastDuration), true,
DataSourceUpdateMode.OnPropertyChanged));
@@ -286,5 +294,10 @@
// Miscellaneous.
ToggleTableRow(tableLayoutPanel13, 0, !_mainForm.Configuration.InfiniteToastDuration);
}
 
private void trackBar1_ValueChanged(object sender, EventArgs e)
{
 
}
}
}
/trunk/Winify/Winify.csproj
@@ -140,6 +140,8 @@
<DependentUpon>AboutForm.cs</DependentUpon>
</Compile>
<Compile Include="Constants.cs" />
<Compile Include="Gotify\GotifyMessageQuery.cs" />
<Compile Include="Gotify\GotifyPaging.cs" />
<Compile Include="LogViewForm.cs">
<SubType>Form</SubType>
</Compile>
@@ -154,7 +156,7 @@
</Compile>
<Compile Include="Gotify\GotifyApplication.cs" />
<Compile Include="Gotify\GotifyConnection.cs" />
<Compile Include="Gotify\GotifyNotification.cs" />
<Compile Include="Gotify\GotifyMessage.cs" />
<Compile Include="Gotify\GotifyNotificationEventArgs.cs" />
<Compile Include="Settings\SettingsSavedEventArgs.cs" />
<Compile Include="Utilities\AES.cs" />