Winify – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 using System;
2 using System.Diagnostics;
3 using System.Drawing;
4 using System.IO;
5 using System.Net;
6 using System.Net.Http;
7 using System.Net.Http.Headers;
8 using System.Net.WebSockets;
9 using System.Text;
10 using System.Threading;
11 using System.Threading.Tasks;
12 using Newtonsoft.Json;
13 using ClientWebSocket = System.Net.WebSockets.Managed.ClientWebSocket;
14  
15 namespace Winify.Gotify
16 {
17 public class GotifyConnection : IDisposable
18 {
19 #region Public Events & Delegates
20  
21 public event EventHandler<GotifyNotificationEventArgs> GotifyNotification;
22  
23 #endregion
24  
25 #region Private Delegates, Events, Enums, Properties, Indexers and Fields
26  
27 private CancellationToken _cancellationToken;
28  
29 private CancellationTokenSource _cancellationTokenSource;
30  
31 private HttpClient _httpClient;
32  
33 private Task _runTask;
34  
35 private ClientWebSocket _webSocketClient;
36  
37 #endregion
38  
39 #region Constructors, Destructors and Finalizers
40  
41 public void Dispose()
42 {
43 if (_cancellationTokenSource != null)
44 {
45 _cancellationTokenSource.Dispose();
46 _cancellationTokenSource = null;
47 }
48  
49 if (_webSocketClient != null)
50 {
51 _webSocketClient.Dispose();
52 _webSocketClient = null;
53 }
54  
55 if (_httpClient != null)
56 {
57 _httpClient.Dispose();
58 _httpClient = null;
59 }
60 }
61  
62 #endregion
63  
64 #region Public Methods
65  
66 public void Start(string username, string password, string host, string port)
67 {
68 if (!Uri.TryCreate($"ws://{host}:{port}/stream", UriKind.RelativeOrAbsolute, out var webSocketsUri))
69 {
70 return;
71 }
72  
73 if (!Uri.TryCreate($"http://{host}:{port}/", UriKind.RelativeOrAbsolute, out var httpUri))
74 {
75 return;
76 }
77  
78 _cancellationTokenSource = new CancellationTokenSource();
79 _cancellationToken = _cancellationTokenSource.Token;
80  
81 var httpClientHandler = new HttpClientHandler
82 {
83 AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
84 };
85  
86 _httpClient = new HttpClient(httpClientHandler)
87 {
88 BaseAddress = httpUri
89 };
90 var auth = Convert.ToBase64String(Encoding.Default.GetBytes($"{username}:{password}"));
91 _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", auth);
92  
93 _runTask = Run(webSocketsUri, username, password, _cancellationToken);
94 }
95  
96 public void Stop()
97 {
98 if (_cancellationTokenSource != null)
99 {
100 _cancellationTokenSource.Cancel();
101 }
102 }
103  
104 #endregion
105  
106 #region Private Methods
107  
108 private async Task Run(Uri uri, string username, string password, CancellationToken cancellationToken)
109 {
110 try
111 {
112 do
113 {
114 try
115 {
116 _webSocketClient = new ClientWebSocket();
117 var auth = Convert.ToBase64String(Encoding.Default.GetBytes($"{username}:{password}"));
118 _webSocketClient.Options.SetRequestHeader("Authorization", $"Basic {auth}");
119  
120 await _webSocketClient.ConnectAsync(uri, cancellationToken);
121  
122 do
123 {
124 var payload = new ArraySegment<byte>(new byte[1024]);
125  
126 await _webSocketClient.ReceiveAsync(payload, cancellationToken);
127  
128 if (payload.Array == null || payload.Count == 0)
129 {
130 continue;
131 }
132  
133 var message = Encoding.UTF8.GetString(payload.Array, 0, payload.Count);
134  
135 var gotifyNotification = JsonConvert.DeserializeObject<GotifyNotification>(message);
136 if (gotifyNotification == null)
137 {
138 continue;
139 }
140  
141 var applications = await _httpClient.GetStringAsync("application");
142  
143 var gotifyApplications = JsonConvert.DeserializeObject<GotifyApplication[]>(applications);
144 if (gotifyApplications == null)
145 {
146 continue;
147 }
148  
149 foreach (var application in gotifyApplications)
150 {
151 if (application.Id != gotifyNotification.AppId)
152 {
153 continue;
154 }
155  
156 var imageBytes = await _httpClient.GetByteArrayAsync(application.Image);
157 using (var memoryStream = new MemoryStream(imageBytes))
158 {
159 var image = Image.FromStream(memoryStream);
160  
161 if (GotifyNotification != null)
162 {
163 GotifyNotification.Invoke(this,
164 new GotifyNotificationEventArgs(gotifyNotification, image));
165 }
166 }
167  
168  
169 break;
170 }
171  
172 Debug.WriteLine($"{gotifyNotification.Message}");
173 } while (!cancellationToken.IsCancellationRequested);
174  
175 await _webSocketClient.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty,
176 CancellationToken.None);
177 }
178 catch (WebSocketException)
179 {
180 // Reconnect
181 if (_webSocketClient != null)
182 {
183 _webSocketClient.Abort();
184 _webSocketClient.Dispose();
185 _webSocketClient = null;
186 }
187  
188 await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
189 }
190 } while (!cancellationToken.IsCancellationRequested);
191 }
192 catch (Exception ex) when (ex is OperationCanceledException || ex is ObjectDisposedException)
193 {
194 }
195 catch (Exception ex)
196 {
197 Debug.WriteLine($"Exception: {ex}");
198 }
199 }
200  
201 #endregion
202 }
203 }