Winify – Rev 9
?pathlinks?
using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
using ClientWebSocket = System.Net.WebSockets.Managed.ClientWebSocket;
namespace Winify.Gotify
{
public class GotifyConnection : IDisposable
{
#region Public Events & Delegates
public event EventHandler<GotifyNotificationEventArgs> GotifyNotification;
#endregion
#region Private Delegates, Events, Enums, Properties, Indexers and Fields
private CancellationToken _cancellationToken;
private CancellationTokenSource _cancellationTokenSource;
private HttpClient _httpClient;
private Task _runTask;
private ClientWebSocket _webSocketClient;
#endregion
#region Constructors, Destructors and Finalizers
public void Dispose()
{
if (_cancellationTokenSource != null)
{
_cancellationTokenSource.Dispose();
_cancellationTokenSource = null;
}
if (_webSocketClient != null)
{
_webSocketClient.Dispose();
_webSocketClient = null;
}
if (_httpClient != null)
{
_httpClient.Dispose();
_httpClient = null;
}
}
#endregion
#region Public Methods
public void Start(string username, string password, string host, string port)
{
if (!Uri.TryCreate($"ws://{host}:{port}/stream", UriKind.RelativeOrAbsolute, out var webSocketsUri))
{
return;
}
if (!Uri.TryCreate($"http://{host}:{port}/", UriKind.RelativeOrAbsolute, out var httpUri))
{
return;
}
_cancellationTokenSource = new CancellationTokenSource();
_cancellationToken = _cancellationTokenSource.Token;
var httpClientHandler = new HttpClientHandler
{
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
};
_httpClient = new HttpClient(httpClientHandler)
{
BaseAddress = httpUri
};
var auth = Convert.ToBase64String(Encoding.Default.GetBytes($"{username}:{password}"));
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", auth);
_runTask = Run(webSocketsUri, username, password, _cancellationToken);
}
public void Stop()
{
if (_cancellationTokenSource != null)
{
_cancellationTokenSource.Cancel();
}
}
#endregion
#region Private Methods
private async Task Run(Uri uri, string username, string password, CancellationToken cancellationToken)
{
try
{
do
{
try
{
_webSocketClient = new ClientWebSocket();
var auth = Convert.ToBase64String(Encoding.Default.GetBytes($"{username}:{password}"));
_webSocketClient.Options.SetRequestHeader("Authorization", $"Basic {auth}");
await _webSocketClient.ConnectAsync(uri, cancellationToken);
do
{
var payload = new ArraySegment<byte>(new byte[1024]);
await _webSocketClient.ReceiveAsync(payload, cancellationToken);
if (payload.Array == null || payload.Count == 0)
{
continue;
}
var message = Encoding.UTF8.GetString(payload.Array, 0, payload.Count);
var gotifyNotification = JsonConvert.DeserializeObject<GotifyNotification>(message);
if (gotifyNotification == null)
{
continue;
}
var applications = await _httpClient.GetStringAsync("application");
var gotifyApplications = JsonConvert.DeserializeObject<GotifyApplication[]>(applications);
if (gotifyApplications == null)
{
continue;
}
foreach (var application in gotifyApplications)
{
if (application.Id != gotifyNotification.AppId)
{
continue;
}
var imageBytes = await _httpClient.GetByteArrayAsync(application.Image);
if (imageBytes == null || imageBytes.Length == 0)
{
continue;
}
using (var memoryStream = new MemoryStream(imageBytes))
{
var image = Image.FromStream(memoryStream);
if (GotifyNotification != null)
{
GotifyNotification.Invoke(this,
new GotifyNotificationEventArgs(gotifyNotification, image));
}
}
break;
}
Debug.WriteLine($"{gotifyNotification.Message}");
} while (!cancellationToken.IsCancellationRequested);
await _webSocketClient.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty,
CancellationToken.None);
}
catch (WebSocketException)
{
// Reconnect
if (_webSocketClient != null)
{
_webSocketClient.Abort();
_webSocketClient.Dispose();
_webSocketClient = null;
}
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
}
} while (!cancellationToken.IsCancellationRequested);
}
catch (Exception ex) when (ex is OperationCanceledException || ex is ObjectDisposedException)
{
}
catch (Exception ex)
{
Debug.WriteLine($"Exception: {ex}");
}
}
#endregion
}
}
Generated by GNU Enscript 1.6.5.90.