Winify – Diff between revs 28 and 35

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