Winify – Diff between revs 35 and 38

Subversion Repositories:
Rev:
Only display areas with differencesIgnore whitespace
Rev 35 Rev 38
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 { -  
125 continue; 124 continue;
126 } -  
127   125  
128 var image = await RetrieveGotifyApplicationImage(gotifyNotification.AppId, httpUri, 126 var image = await RetrieveGotifyApplicationImage(gotifyNotification.AppId, httpUri,
129 applicationUri, auth, cancellationToken); 127 applicationUri, auth, cancellationToken);
130   128  
131 GotifyNotification?.Invoke(this, 129 GotifyNotification?.Invoke(this,
132 new GotifyNotificationEventArgs(gotifyNotification, image)); 130 new GotifyNotificationEventArgs(gotifyNotification, image));
133   131  
134 Log.Debug($"Notification message received: {gotifyNotification.Message}"); 132 Log.Debug($"Notification message received: {gotifyNotification.Message}");
135 } while (!cancellationToken.IsCancellationRequested); 133 } while (!cancellationToken.IsCancellationRequested);
136 } 134 }
137 } 135 }
138 catch (Exception ex) when (ex is WebSocketException || ex is HttpRequestException) 136 catch (Exception ex) when (ex is WebSocketException || ex is HttpRequestException)
139 { 137 {
140 // Reconnect 138 // Reconnect
141 Log.Warning($"Unable to connect to gotify server: {ex.Message}"); 139 Log.Warning($"Unable to connect to gotify server: {ex.Message}");
142   140  
143 await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken); 141 await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
144 } 142 }
145 } while (!cancellationToken.IsCancellationRequested); 143 } while (!cancellationToken.IsCancellationRequested);
146 } 144 }
147 catch (Exception ex) when (ex is OperationCanceledException || ex is ObjectDisposedException) 145 catch (Exception ex) when (ex is OperationCanceledException || ex is ObjectDisposedException)
148 { 146 {
149 } 147 }
150 catch (Exception ex) 148 catch (Exception ex)
151 { 149 {
152 Log.Warning(ex, "Failure running connection loop."); 150 Log.Warning(ex, "Failure running connection loop.");
153 } 151 }
154 } 152 }
155   153  
156 private static async Task<Image> RetrieveGotifyApplicationImage(int appId, Uri httpUri, Uri applicationUri, 154 private static async Task<Image> RetrieveGotifyApplicationImage(int appId, Uri httpUri, Uri applicationUri,
157 string auth, 155 string auth,
158 CancellationToken cancellationToken) 156 CancellationToken cancellationToken)
159 { 157 {
160 using (var httpClient = new HttpClient()) 158 using (var httpClient = new HttpClient())
161 { 159 {
162 httpClient.DefaultRequestHeaders.Authorization = 160 httpClient.DefaultRequestHeaders.Authorization =
163 new AuthenticationHeaderValue("Basic", auth); 161 new AuthenticationHeaderValue("Basic", auth);
164   162  
165 var applicationResponse = await httpClient.GetAsync(applicationUri, cancellationToken); 163 var applicationResponse = await httpClient.GetAsync(applicationUri, cancellationToken);
166   164  
167 var applications = await applicationResponse.Content.ReadAsStringAsync(); 165 var applications = await applicationResponse.Content.ReadAsStringAsync();
168   166  
169 var gotifyApplications = 167 var gotifyApplications =
170 JsonConvert.DeserializeObject<GotifyApplication[]>(applications); 168 JsonConvert.DeserializeObject<GotifyApplication[]>(applications);
171   169  
172 if (gotifyApplications == null) return null; 170 if (gotifyApplications == null) return null;
173   171  
174 foreach (var application in gotifyApplications) 172 foreach (var application in gotifyApplications)
175 { 173 {
176 if (application.Id != appId) continue; 174 if (application.Id != appId) continue;
177   175  
178 if (!Uri.TryCreate(Path.Combine($"{httpUri}", $"{application.Image}"), UriKind.Absolute, 176 if (!Uri.TryCreate(Path.Combine($"{httpUri}", $"{application.Image}"), UriKind.Absolute,
179 out var applicationImageUri)) 177 out var applicationImageUri))
180 continue; 178 continue;
181   179  
182 var imageResponse = await httpClient.GetAsync(applicationImageUri, cancellationToken); 180 var imageResponse = await httpClient.GetAsync(applicationImageUri, cancellationToken);
183   181  
184 using (var memoryStream = new MemoryStream()) 182 using (var memoryStream = new MemoryStream())
185 { 183 {
186 await imageResponse.Content.CopyToAsync(memoryStream); 184 await imageResponse.Content.CopyToAsync(memoryStream);
187   185  
188 return Image.FromStream(memoryStream); 186 return Image.FromStream(memoryStream);
189 } 187 }
190 } 188 }
191 } 189 }
192   190  
193 return null; 191 return null;
194 } 192 }
195   193  
196 #endregion 194 #endregion
197 } 195 }
198 } 196 }
199   197  
200
Generated by GNU Enscript 1.6.5.90.
198
Generated by GNU Enscript 1.6.5.90.
201   199  
202   200  
203   201