forked from baaron4/GW2-Elite-Insights-Parser
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathWingmanController.cs
318 lines (291 loc) · 12.7 KB
/
WingmanController.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
using System.Net;
using System.Text;
using GW2EIWingman.WingmanUploadJsons;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
[assembly: CLSCompliant(false)]
namespace GW2EIWingman;
/// <summary>
/// https://gw2wingman.nevermindcreations.de/api
/// </summary>
public static class WingmanController
{
public delegate void TraceHandler(string trace);
private static readonly DefaultContractResolver DefaultJsonContractResolver = new()
{
NamingStrategy = new CamelCaseNamingStrategy()
};
private static readonly UTF8Encoding NoBOMEncodingUTF8 = new(false);
private static readonly HttpClient HTTPClient = new HttpClient()
{
Timeout = Timeout.InfiniteTimeSpan
};
///////////////// URL Utilities
private const string BaseURL = "https://gw2wingman.nevermindcreations.de/";
private const string TestConnectionURL = BaseURL + "testConnection";
private const string BaseAPIURL = BaseURL + "api/";
private const string EIVersionURL = BaseAPIURL + "EIversion";
private const string ImportLogQueuedURL = BaseAPIURL + "importLogQueued";
private const string CheckLogQueuedURL = BaseAPIURL + "checkLogQueued";
private const string CheckLogQueuedOrDBURL = BaseAPIURL + "checkLogQueuedOrDB";
private const string CheckUploadURL = BaseURL + "checkUpload";
private const string UploadProcessedURL = BaseURL + "uploadProcessed";
private static bool IsDPSReportLinkValid(string dpsReportLink, TraceHandler traceHandler)
{
if (!dpsReportLink.Contains("https") && !dpsReportLink.Contains(".report"))
{
traceHandler("Invalid dps.report link");
return false;
}
return true;
}
private static string GetImportLogQueuedURL(string dpsReportLink)
{
return ImportLogQueuedURL + "?link=" + dpsReportLink;
}
private static string GetCheckLogQueuedURL(string dpsReportLink)
{
return CheckLogQueuedURL + "?link=" + dpsReportLink;
}
private static string GetCheckLogQueuedOrDBURL(string dpsReportLink)
{
return CheckLogQueuedOrDBURL + "?link=" + dpsReportLink;
}
// Connection checking
private static bool CheckConnection(TraceHandler traceHandler)
{
bool check = _GetWingmanResponse("CheckConnection", TestConnectionURL, traceHandler, HttpMethod.Get) == "True";
traceHandler("connection " + (check ? "OK" : "KO"));
return check;
}
private static bool VerifyEIVersion(Version parserVersion, TraceHandler traceHandler)
{
string? returnedVersion = _GetWingmanResponse("EIVersionURL", EIVersionURL, traceHandler, HttpMethod.Get);
if (returnedVersion == null)
{
traceHandler("Could not fetch version from Wingman");
return true;
}
returnedVersion = returnedVersion.Replace("v", "");
var expectedVersion = new Version(returnedVersion);
traceHandler("Used version " + parserVersion.ToString());
bool check = parserVersion.CompareTo(expectedVersion) >= 0;
traceHandler("Version " + (check ? "up to date" : "outdated"));
if (!check)
{
traceHandler("Expected version to be at least " + expectedVersion.ToString() + ", please update your EI.");
}
return true;
}
public static bool CanBeUsed(Version? parserVersion, TraceHandler traceHandler)
{
return CheckConnection(traceHandler) && (parserVersion == null || VerifyEIVersion(parserVersion, traceHandler));
}
//
public static WingmanCheckLogQueuedOrDBObject? GetCheckLogQueuedOrDB(string dpsReportLink, TraceHandler traceHandler)
{
if (!IsDPSReportLinkValid(dpsReportLink, traceHandler))
{
return null;
}
try
{
return JsonConvert.DeserializeObject<WingmanCheckLogQueuedOrDBObject>(GetWingmanResponse("CheckLogQueuedOrDB", GetCheckLogQueuedOrDBURL(dpsReportLink), traceHandler, null, HttpMethod.Post)!, new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
ContractResolver = DefaultJsonContractResolver,
StringEscapeHandling = StringEscapeHandling.EscapeHtml
});
}
catch (Exception e)
{
traceHandler("CheckLogQueuedOrDB failed - " + e.Message);
return null;
}
}
public static WingmanCheckLogQueuedObject? GetCheckLogQueued(string dpsReportLink, TraceHandler traceHandler)
{
if (!IsDPSReportLinkValid(dpsReportLink, traceHandler))
{
return null;
}
try
{
return JsonConvert.DeserializeObject<WingmanCheckLogQueuedObject>(GetWingmanResponse("CheckLogQueued", GetCheckLogQueuedOrDBURL(dpsReportLink), traceHandler, null, HttpMethod.Post)!, new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
ContractResolver = DefaultJsonContractResolver,
StringEscapeHandling = StringEscapeHandling.EscapeHtml
});
}
catch (Exception e)
{
traceHandler("CheckLogQueued failed - " + e.Message);
return null;
}
}
public static WingmanImportLogQueuedObject? ImportLogQueued(string dpsReportLink, TraceHandler traceHandler)
{
if (!IsDPSReportLinkValid(dpsReportLink, traceHandler))
{
return null;
}
try
{
return JsonConvert.DeserializeObject<WingmanImportLogQueuedObject>(GetWingmanResponse("ImportLogQueued", GetCheckLogQueuedOrDBURL(dpsReportLink), traceHandler, null, HttpMethod.Post)!, new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
ContractResolver = DefaultJsonContractResolver,
StringEscapeHandling = StringEscapeHandling.EscapeHtml
});
}
catch (Exception e)
{
traceHandler("ImportLogQueued failed - " + e.Message);
return null;
}
}
public static bool UploadToWingmanUsingImportLogQueued(string dpsReportLink, TraceHandler traceHandler)
{
// Check if the URL is already present on Wingman
WingmanCheckLogQueuedOrDBObject? wingmanCheck = GetCheckLogQueuedOrDB(dpsReportLink, traceHandler);
if (wingmanCheck != null)
{
if (wingmanCheck.InDB || wingmanCheck.InQueue)
{
traceHandler("Upload failed - Log already present in Wingman DB");
return false;
}
else
{
WingmanImportLogQueuedObject? wingmanUpload = ImportLogQueued(dpsReportLink, traceHandler);
if (wingmanUpload != null)
{
if (wingmanUpload.Success != 1)
{
traceHandler("Upload failed - " + wingmanUpload.Note);
return true;
}
else
{
traceHandler("Upload successful - " + wingmanUpload.Note);
return true;
}
}
return false;
}
}
return false;
}
public static bool CheckUploadPossible(FileInfo fi, string account, long triggerID, TraceHandler traceHandler)
{
string creationTime = new DateTimeOffset(fi.CreationTime).ToUnixTimeSeconds().ToString();
var data = new Dictionary<string, string> {
{ "account", account },
{ "filesize", fi.Length.ToString() },
{ "timestamp", creationTime },
{ "file", fi.Name } ,
{ "triggerID", triggerID.ToString() }
};
HttpContent contentCreator()
{
var multiPartContent = new MultipartFormDataContent();
foreach (KeyValuePair<string, string> pair in data)
{
var content = new StringContent(pair.Value, NoBOMEncodingUTF8, "text/plain");
multiPartContent.Add(content, pair.Key);
}
return multiPartContent;
}
return GetWingmanResponse("CheckUploadPossible", CheckUploadURL, traceHandler, null, HttpMethod.Post, contentCreator) == "True";
}
public static bool UploadProcessed(FileInfo fi, string account, byte[] jsonFile, byte[] htmlFile, string suffix, TraceHandler traceHandler, Version parserVersion)
{
//var data = new Dictionary<string, string> { { "account", account }, { "file", File.ReadAllText(fi.FullName) }, { "jsonfile", jsonString }, { "htmlfile", htmlString } };
byte[] fileBytes = File.ReadAllBytes(fi.FullName);
string name = fi.Name;
string jsonName = Path.GetFileNameWithoutExtension(fi.Name) + suffix + ".json";
string htmlName = Path.GetFileNameWithoutExtension(fi.Name) + suffix + ".html";
string jsonString = NoBOMEncodingUTF8.GetString(jsonFile);
string htmlString = NoBOMEncodingUTF8.GetString(htmlFile);
var data = new Dictionary<string, string> {
{ "account", account },
};
Func<HttpContent> contentCreator = () =>
{
var multiPartContent = new MultipartFormDataContent();
var fileContent = new ByteArrayContent(fileBytes);
fileContent.Headers.Add("Content-Type", "application/octet-stream");
multiPartContent.Add(fileContent, "file", name);
var jsonContent = new StringContent(jsonString, NoBOMEncodingUTF8, "text/plain");
multiPartContent.Add(jsonContent, "jsonfile", jsonName);
var htmlContent = new StringContent(htmlString, NoBOMEncodingUTF8, "text/plain");
multiPartContent.Add(htmlContent, "htmlfile", htmlName);
foreach (KeyValuePair<string, string> pair in data)
{
var content = new StringContent(pair.Value, NoBOMEncodingUTF8, "text/plain");
multiPartContent.Add(content, pair.Key);
}
return multiPartContent;
};
string? response = GetWingmanResponse("UploadProcessed", UploadProcessedURL, traceHandler, null, HttpMethod.Post, contentCreator);
return response != null && response != "False";
}
//
private static string? _GetWingmanResponse(string requestName, string url, TraceHandler traceHandler, HttpMethod method, Func<HttpContent>? content = null)
{
const int tentatives = 3;
for (int i = 0; i < tentatives; i++)
{
traceHandler(requestName + " tentative");
var webService = new Uri(@url);
using var requestMessage = new HttpRequestMessage(method, webService);
requestMessage.Headers.ExpectContinue = false;
if (content != null)
{
requestMessage.Content = content();
}
try
{
Task<HttpResponseMessage> httpRequest = HTTPClient.SendAsync(requestMessage, HttpCompletionOption.ResponseContentRead);
HttpResponseMessage httpResponse = httpRequest.Result;
HttpStatusCode statusCode = httpResponse.StatusCode;
HttpContent responseContent = httpResponse.Content;
if (statusCode != HttpStatusCode.OK)
{
throw new HttpRequestException(statusCode.ToString());
}
if (responseContent != null)
{
Task<string> stringContentsTask = responseContent.ReadAsStringAsync();
string stringContents = stringContentsTask.Result;
traceHandler(requestName + " successful: " + stringContents);
return stringContents;
}
}
catch (AggregateException agg)
{
traceHandler(requestName + " tentative failed");
traceHandler("Main reason: " + agg.Message);
foreach (Exception e in agg.InnerExceptions)
{
traceHandler(requestName + " tentaive failed - sub message - " + e.Message);
}
}
catch (Exception e)
{
traceHandler(requestName + " tentaive failed");
traceHandler("Reason: " + e.Message);
}
}
return null;
}
private static string? GetWingmanResponse(string requestName, string url, TraceHandler traceHandler, Version? parserVersion, HttpMethod method, Func<HttpContent>? content = null)
{
if (!CanBeUsed(parserVersion, traceHandler))
{
return default;
}
return _GetWingmanResponse(requestName, url, traceHandler, method, content);
}
}