Winify – Diff between revs 24 and 25

Subversion Repositories:
Rev:
Only display areas with differencesIgnore whitespace
Rev 24 Rev 25
1 using System; 1 using System;
2 using System.Drawing; 2 using System.Drawing;
3 using System.IO; 3 using System.IO;
4 using System.Net.Http; 4 using System.Net.Http;
5 using System.Net.Http.Headers; 5 using System.Net.Http.Headers;
6 using System.Net.WebSockets; 6 using System.Net.WebSockets;
7 using System.Text; 7 using System.Text;
8 using System.Threading; 8 using System.Threading;
9 using System.Threading.Tasks; 9 using System.Threading.Tasks;
10 using Newtonsoft.Json; 10 using Newtonsoft.Json;
11 using Serilog; 11 using Serilog;
12 using Servers; 12 using Servers;
13 using ClientWebSocket = System.Net.WebSockets.Managed.ClientWebSocket; 13 using ClientWebSocket = System.Net.WebSockets.Managed.ClientWebSocket;
14   14  
15 namespace Winify.Gotify 15 namespace Winify.Gotify
16 { 16 {
17 public class GotifyConnection : IDisposable 17 public class GotifyConnection : IDisposable
18 { 18 {
19 #region Public Events & Delegates 19 #region Public Events & Delegates
20   20  
21 public event EventHandler<GotifyNotificationEventArgs> GotifyNotification; 21 public event EventHandler<GotifyNotificationEventArgs> GotifyNotification;
22   22  
23 #endregion 23 #endregion
24   24  
25 #region Private Delegates, Events, Enums, Properties, Indexers and Fields 25 #region Private Delegates, Events, Enums, Properties, Indexers and Fields
-   26  
-   27 private readonly Server _server;
26   28  
27 private CancellationToken _cancellationToken; 29 private CancellationToken _cancellationToken;
28   30  
29 private CancellationTokenSource _cancellationTokenSource; 31 private CancellationTokenSource _cancellationTokenSource;
30   -  
31 private HttpClient _httpClient; -  
32   32  
33 private Task _runTask; 33 private Task _runTask;
34   34  
35 private ClientWebSocket _webSocketClient; 35 #endregion
36   36  
37 private readonly Server _server; 37 #region Constructors, Destructors and Finalizers
38   38  
39 public GotifyConnection(Server server) 39 public GotifyConnection(Server server)
40 { 40 {
41 _server = server; 41 _server = server;
42 } 42 }
43   -  
44 #endregion -  
45   -  
46 #region Constructors, Destructors and Finalizers -  
47   43  
48 public void Dispose() 44 public void Dispose()
49 { 45 {
50 if (_cancellationTokenSource != null) 46 if (_cancellationTokenSource != null)
51 { 47 {
52 _cancellationTokenSource.Dispose(); 48 _cancellationTokenSource.Dispose();
53 _cancellationTokenSource = null; 49 _cancellationTokenSource = null;
54 } 50 }
55   -  
56 if (_webSocketClient != null) -  
57 { -  
58 _webSocketClient.Dispose(); -  
59 _webSocketClient = null; -  
60 } -  
61   -  
62 if (_httpClient != null) -  
63 { -  
64 _httpClient.Dispose(); -  
65 _httpClient = null; -  
66 } -  
67 } 51 }
68   52  
69 #endregion 53 #endregion
70   54  
71 #region Public Methods 55 #region Public Methods
72   56  
73 public void Start(string username, string password, string url) 57 public void Start()
74 { 58 {
75 if (!Uri.TryCreate(url, UriKind.Absolute, out var httpUri)) 59 if (!Uri.TryCreate(_server.Url, UriKind.Absolute, out var httpUri))
76 { 60 {
77 return; 61 return;
78 } 62 }
79   63  
80 // Build the web sockets URI. 64 // Build the web sockets URI.
81 var webSocketsUriBuilder = new UriBuilder(httpUri); 65 var webSocketsUriBuilder = new UriBuilder(httpUri);
82 webSocketsUriBuilder.Scheme = "ws"; 66 webSocketsUriBuilder.Scheme = "ws";
83 webSocketsUriBuilder.Path = $"{webSocketsUriBuilder.Path}/stream"; 67 webSocketsUriBuilder.Path = $"{webSocketsUriBuilder.Path}/stream";
84 var webSocketsUri = webSocketsUriBuilder.Uri; 68 var webSocketsUri = webSocketsUriBuilder.Uri;
85   69  
86 _cancellationTokenSource = new CancellationTokenSource(); 70 _cancellationTokenSource = new CancellationTokenSource();
87 _cancellationToken = _cancellationTokenSource.Token; 71 _cancellationToken = _cancellationTokenSource.Token;
88   -  
89 _httpClient = new HttpClient(); -  
90   -  
91 var auth = Convert.ToBase64String(Encoding.Default.GetBytes($"{username}:{password}")); -  
92   -  
93 _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", auth); -  
94   72  
95 _runTask = Run(webSocketsUri, httpUri, username, password, _cancellationToken); 73 _runTask = Run(webSocketsUri, httpUri, _server.Username, _server.Password, _cancellationToken);
96 } 74 }
97   75  
98 public void Stop() 76 public void Stop()
99 { 77 {
100 if (_cancellationTokenSource != null) 78 if (_cancellationTokenSource != null)
101 { 79 {
102 _cancellationTokenSource.Cancel(); 80 _cancellationTokenSource.Cancel();
103 } 81 }
104   -  
105 _runTask.Wait(CancellationToken.None); -  
106 } 82 }
107   83  
108 #endregion 84 #endregion
109   85  
110 #region Private Methods 86 #region Private Methods
111   87  
112 private async Task Run(Uri webSocketsUri, Uri httpUri, string username, string password, 88 private async Task Run(Uri webSocketsUri, Uri httpUri, string username, string password,
113 CancellationToken cancellationToken) 89 CancellationToken cancellationToken)
114 { 90 {
115 try 91 try
116 { 92 {
117 do 93 do
118 { 94 {
119 try 95 try
120 { 96 {
121 using (_webSocketClient = new ClientWebSocket()) 97 using (var webSocketClient = new ClientWebSocket())
122 { 98 {
123 var auth = Convert.ToBase64String(Encoding.Default.GetBytes($"{username}:{password}")); 99 var auth = Convert.ToBase64String(Encoding.Default.GetBytes($"{username}:{password}"));
124   100  
125 _webSocketClient.Options.SetRequestHeader("Authorization", $"Basic {auth}"); 101 webSocketClient.Options.SetRequestHeader("Authorization", $"Basic {auth}");
126   102  
127 await _webSocketClient.ConnectAsync(webSocketsUri, cancellationToken); 103 await webSocketClient.ConnectAsync(webSocketsUri, cancellationToken);
128   104  
129 do 105 do
130 { 106 {
131 var payload = new ArraySegment<byte>(new byte[1024]); 107 var payload = new ArraySegment<byte>(new byte[1024]);
132   108  
133 var result = await _webSocketClient.ReceiveAsync(payload, cancellationToken); 109 var result = await webSocketClient.ReceiveAsync(payload, cancellationToken);
134   110  
135 if (result.Count == 0) 111 if (result.Count == 0)
136 { 112 {
137 continue; 113 continue;
138 } 114 }
139   115  
140 if (payload.Array == null || payload.Count == 0) 116 if (payload.Array == null || payload.Count == 0)
141 { 117 {
142 continue; 118 continue;
143 } 119 }
144   120  
145 var message = Encoding.UTF8.GetString(payload.Array, 0, payload.Count); 121 var message = Encoding.UTF8.GetString(payload.Array, 0, payload.Count);
146   122  
147 var gotifyNotification = JsonConvert.DeserializeObject<GotifyNotification>(message); 123 if (!(JsonConvert.DeserializeObject<GotifyNotification>(message) is GotifyNotification
148 if (gotifyNotification == null) 124 gotifyNotification))
149 { 125 {
150 continue; -  
151 } -  
152   -  
153 gotifyNotification.Server = _server; -  
154   -  
155 if (!Uri.TryCreate($"{httpUri}/application", UriKind.Absolute, out var applicationUri)) 126 Log.Warning($"Could not deserialize gotify notification: {message}");
156 { 127  
157 continue; 128 continue;
158 } 129 }
159   130  
160 var applications = await _httpClient.GetStringAsync(applicationUri); -  
161   131 gotifyNotification.Server = _server;
162 var gotifyApplications = 132  
163 JsonConvert.DeserializeObject<GotifyApplication[]>(applications); 133 if (!Uri.TryCreate($"{httpUri}/application", UriKind.Absolute,
164 if (gotifyApplications == null) 134 out var applicationUri))
165 { 135 {
166 continue; 136 continue;
167 } 137 }
168   -  
169 foreach (var application in gotifyApplications) -  
170 { 138  
171 if (application.Id != gotifyNotification.AppId) -  
172 { -  
173 continue; -  
174 } -  
175   -  
176 if (!Uri.TryCreate($"{httpUri}/{application.Image}", UriKind.Absolute, 139 var image = await RetrieveGotifyApplicationImage(gotifyNotification.AppId, httpUri,
177 out var applicationImageUri)) -  
178 { -  
179 continue; -  
180 } -  
181   -  
182 var imageBytes = await _httpClient.GetByteArrayAsync(applicationImageUri); -  
183   -  
184 if (imageBytes == null || imageBytes.Length == 0) -  
185 { -  
186 continue; -  
187 } -  
188   -  
189 using (var memoryStream = new MemoryStream(imageBytes)) -  
190 { -  
191 var image = Image.FromStream(memoryStream); -  
192   -  
193 GotifyNotification?.Invoke(this, -  
194 new GotifyNotificationEventArgs(gotifyNotification, image)); -  
195 } -  
196   140 applicationUri, auth, cancellationToken);
197   141  
198 break; 142 GotifyNotification?.Invoke(this,
199 } 143 new GotifyNotificationEventArgs(gotifyNotification, image));
200   144  
201 Log.Debug($"Notification message received: {gotifyNotification.Message}"); 145 Log.Debug($"Notification message received: {gotifyNotification.Message}");
202 } while (!cancellationToken.IsCancellationRequested); 146 } while (!cancellationToken.IsCancellationRequested);
203   -  
204 await _webSocketClient.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, -  
205 CancellationToken.None); -  
206 } 147 }
207   -  
208 _webSocketClient = null; -  
209 } 148 }
210 catch (Exception ex) when (ex is WebSocketException || ex is HttpRequestException) 149 catch (Exception ex) when (ex is WebSocketException || ex is HttpRequestException)
211 { 150 {
212 Log.Warning($"Unable to connect to gotify server: {ex.Message}"); -  
213   -  
214 // Reconnect 151 // Reconnect
215 if (_webSocketClient != null) -  
216 { -  
217 _webSocketClient.Abort(); -  
218 _webSocketClient.Dispose(); 152 Log.Warning($"Unable to connect to gotify server: {ex.Message}");
219 _webSocketClient = null; -  
220 } -  
221   153  
222 await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken); 154 await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
223 } 155 }
224 } while (!cancellationToken.IsCancellationRequested); 156 } while (!cancellationToken.IsCancellationRequested);
225 } 157 }
226 catch (Exception ex) when (ex is OperationCanceledException || ex is ObjectDisposedException) 158 catch (Exception ex) when (ex is OperationCanceledException || ex is ObjectDisposedException)
227 { 159 {
228 } 160 }
229 catch (Exception ex) 161 catch (Exception ex)
230 { 162 {
231 Log.Warning(ex, "Failure running connection loop."); 163 Log.Warning(ex, "Failure running connection loop.");
232 } 164 }
-   165  
-   166 var e = "o";
-   167 }
-   168  
-   169 private static async Task<Image> RetrieveGotifyApplicationImage(int appId, Uri httpUri, Uri applicationUri,
-   170 string auth,
-   171 CancellationToken cancellationToken)
-   172 {
-   173 using (var httpClient = new HttpClient())
-   174 {
-   175 httpClient.DefaultRequestHeaders.Authorization =
-   176 new AuthenticationHeaderValue("Basic", auth);
-   177  
-   178 var applicationResponse = await httpClient.GetAsync(applicationUri, cancellationToken);
-   179  
-   180 var applications = await applicationResponse.Content.ReadAsStringAsync();
-   181  
-   182 var gotifyApplications =
-   183 JsonConvert.DeserializeObject<GotifyApplication[]>(applications);
-   184  
-   185 if (gotifyApplications == null)
-   186 {
-   187 return null;
-   188 }
-   189  
-   190 foreach (var application in gotifyApplications)
-   191 {
-   192 if (application.Id != appId)
-   193 {
-   194 continue;
-   195 }
-   196  
-   197 if (!Uri.TryCreate($"{httpUri}/{application.Image}", UriKind.Absolute,
-   198 out var applicationImageUri))
-   199 {
-   200 continue;
-   201 }
-   202  
-   203 var imageResponse = await httpClient.GetAsync(applicationImageUri, cancellationToken);
-   204  
-   205 using (var memoryStream = new MemoryStream())
-   206 {
-   207 await imageResponse.Content.CopyToAsync(memoryStream);
-   208  
-   209 return Image.FromStream(memoryStream);
-   210 }
-   211 }
-   212 }
-   213  
-   214 return null;
233 } 215 }
234   216  
235 #endregion 217 #endregion
236 } 218 }
237 } 219 }
238   220  
239
Generated by GNU Enscript 1.6.5.90.
221
Generated by GNU Enscript 1.6.5.90.
240   222  
241   223  
242   224