Winify – Rev 39
?pathlinks?
using System;
using System.Drawing;
using System.IO;
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 Serilog;
using Servers;
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 readonly Server _server;
private CancellationToken _cancellationToken;
private CancellationTokenSource _cancellationTokenSource;
private Task _runTask;
private HttpClient _httpClient;
private readonly string _auth;
private readonly Uri _webSocketsUri;
private readonly Uri _httpUri;
#endregion
#region Constructors, Destructors and Finalizers
public GotifyConnection()
{
_httpClient = new HttpClient();
}
public GotifyConnection(Server server) : this()
{
_server = server;
_auth = Convert.ToBase64String(Encoding.Default.GetBytes($"{_server.Username}:{_server.Password}"));
_httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Basic", _auth);
if (Uri.TryCreate(_server.Url, UriKind.Absolute, out _httpUri))
{
// Build the web sockets URI.
var webSocketsUriBuilder = new UriBuilder(_httpUri);
webSocketsUriBuilder.Scheme = "ws";
webSocketsUriBuilder.Path = Path.Combine(webSocketsUriBuilder.Path, "stream");
_webSocketsUri = webSocketsUriBuilder.Uri;
}
}
public void Dispose()
{
if (_cancellationTokenSource != null)
{
_cancellationTokenSource.Dispose();
_cancellationTokenSource = null;
}
_httpClient.Dispose();
_httpClient = null;
}
#endregion
#region Public Methods
public void Start()
{
_cancellationTokenSource = new CancellationTokenSource();
_cancellationToken = _cancellationTokenSource.Token;
_runTask = Run(_cancellationToken);
}
public void Stop()
{
if (_cancellationTokenSource != null)
{
_cancellationTokenSource.Cancel();
}
}
#endregion
#region Private Methods
private async Task Run(CancellationToken cancellationToken)
{
try
{
do
{
try
{
using (var webSocketClient = new ClientWebSocket())
{
webSocketClient.Options.SetRequestHeader("Authorization", $"Basic {_auth}");
await webSocketClient.ConnectAsync(_webSocketsUri, cancellationToken);
do
{
var payload = new ArraySegment<byte>(new byte[1024]);
var result = await webSocketClient.ReceiveAsync(payload, cancellationToken);
if (result.Count == 0)
{
continue;
}
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)
{
Log.Warning($"Could not deserialize gotify notification: {message}");
continue;
}
gotifyNotification.Server = _server;
if (!Uri.TryCreate(Path.Combine($"{_httpUri}", "application"), UriKind.Absolute,
out var applicationUri))
{
continue;
}
var image = await RetrieveGotifyApplicationImage(gotifyNotification.AppId,
applicationUri, cancellationToken);
GotifyNotification?.Invoke(this,
new GotifyNotificationEventArgs(gotifyNotification, image));
Log.Debug($"Notification message received: {gotifyNotification.Message}");
} while (!cancellationToken.IsCancellationRequested);
}
}
catch (Exception ex) when (ex is WebSocketException || ex is HttpRequestException)
{
// Reconnect
Log.Warning($"Unable to connect to gotify server: {ex.Message}");
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
}
} while (!cancellationToken.IsCancellationRequested);
}
catch (Exception ex) when (ex is OperationCanceledException || ex is ObjectDisposedException)
{
}
catch (Exception ex)
{
Log.Warning(ex, "Failure running connection loop.");
}
}
private async Task<Image> RetrieveGotifyApplicationImage(int appId, Uri applicationUri,
CancellationToken cancellationToken)
{
var applicationResponse = await _httpClient.GetAsync(applicationUri, cancellationToken);
var applications = await applicationResponse.Content.ReadAsStringAsync();
var gotifyApplications =
JsonConvert.DeserializeObject<GotifyApplication[]>(applications);
if (gotifyApplications == null)
{
return null;
}
foreach (var application in gotifyApplications)
{
if (application.Id != appId)
{
continue;
}
if (!Uri.TryCreate(Path.Combine($"{_httpUri}", $"{application.Image}"), UriKind.Absolute,
out var applicationImageUri))
{
continue;
}
var imageResponse = await _httpClient.GetAsync(applicationImageUri, cancellationToken);
using (var memoryStream = new MemoryStream())
{
await imageResponse.Content.CopyToAsync(memoryStream);
return Image.FromStream(memoryStream);
}
}
return null;
}
#endregion
}
}
Generated by GNU Enscript 1.6.5.90.