Winify – Diff between revs 38 and 39

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