Skip to content

Commit d12c370

Browse files
committed
Add wingman re-ping after unsuccessful log uploads
1 parent eba18d5 commit d12c370

4 files changed

Lines changed: 184 additions & 40 deletions

File tree

Forms/FormMain.cs

Lines changed: 51 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public partial class FormMain : Form
5757
private readonly FormLogSession logSessionLink;
5858
private readonly FormPings pingsLink;
5959
private readonly FormTeams teamsLink;
60-
private readonly Timer timerFailedLogsReupload = new()
60+
private readonly Timer timerFailedLogsReuploadAndRePing = new()
6161
{
6262
Enabled = false,
6363
Interval = 900000,
@@ -324,7 +324,7 @@ internal FormMain()
324324
logSessionLink.checkBoxOnlySuccess.CheckedChanged += logSessionLink.CheckBoxOnlySuccess_CheckedChanged;
325325
logSessionLink.checkBoxSaveToFile.CheckedChanged += logSessionLink.CheckBoxSaveToFile_CheckedChanged;
326326
discordWebhooksLink.checkBoxShortenThousands.CheckedChanged += discordWebhooksLink.CheckBoxShortenThousands_CheckedChanged;
327-
timerFailedLogsReupload.Elapsed += TimerFailedLogsReupload_Elapsed;
327+
timerFailedLogsReuploadAndRePing.Elapsed += TimerFailedLogsReuploadAndRePingElapsed;
328328
timerCheckUpdate.Elapsed += TimerCheckUpdate_Elapsed;
329329
ApplicationSettings.Current.Save();
330330
}
@@ -634,6 +634,7 @@ private async Task StartUpAndCommandArgs()
634634
if (args.Length <= 1)
635635
{
636636
HandleLogReuploads();
637+
HandleWingmanRePings();
637638
return;
638639
}
639640
var argIndex = -1;
@@ -667,32 +668,33 @@ private async Task StartUpAndCommandArgs()
667668
if (File.Exists(arg) && (arg.EndsWith(".evtc") || arg.EndsWith(".zevtc")))
668669
{
669670
var archived = false;
670-
var zipfilelocation = arg;
671+
var zipFileLocation = arg;
671672
if (!arg.EndsWith(".zevtc"))
672673
{
673-
zipfilelocation = $"{ApplicationSettings.LocalDir}{Path.GetFileNameWithoutExtension(arg)}.zevtc";
674-
using var zipfile = ZipFile.Open(zipfilelocation, ZipArchiveMode.Create);
675-
zipfile.CreateEntryFromFile(arg, Path.GetFileName(arg));
674+
zipFileLocation = $"{ApplicationSettings.LocalDir}{Path.GetFileNameWithoutExtension(arg)}.zevtc";
675+
using var zipFile = ZipFile.Open(zipFileLocation, ZipArchiveMode.Create);
676+
zipFile.CreateEntryFromFile(arg, Path.GetFileName(arg));
676677
archived = true;
677678
}
678679
try
679680
{
680-
await HttpUploadLogAsync(zipfilelocation, defaultPostData);
681+
await HttpUploadLogAsync(zipFileLocation, defaultPostData);
681682
}
682683
catch
683684
{
684-
AddToText($">>> Unknown error uploading a log: {zipfilelocation}");
685+
AddToText($">>> Unknown error uploading a log: {zipFileLocation}");
685686
}
686687
finally
687688
{
688689
if (archived)
689690
{
690-
File.Delete(zipfilelocation);
691+
File.Delete(zipFileLocation);
691692
}
692693
}
693694
}
694695
}
695696
HandleLogReuploads();
697+
HandleWingmanRePings();
696698
}
697699

698700
private async Task ValidateGw2Tokens()
@@ -787,19 +789,19 @@ private async Task HttpUploadLogAsync(string file, Dictionary<string, string> po
787789
if (reportJson?.Error?.Contains("EI Failure") ?? false)
788790
{
789791
AddToText(">:> Due to an Elite Insights error while processing the log file, it will not be automatically reuploaded. Is the log file corrupted?");
790-
LogReuploader.RemovedLogAndSave(file);
792+
LogReuploader.RemoveLogAndSave(file);
791793
return;
792794
}
793795
if (reportJson?.Error?.Contains("An identical file was uploaded recently") ?? false)
794796
{
795797
AddToText(">:> To prevent same log regeneration, the upload try will not be automatically reuploaded.");
796-
LogReuploader.RemovedLogAndSave(file);
798+
LogReuploader.RemoveLogAndSave(file);
797799
return;
798800
}
799801
if (reportJson?.Error?.Contains("Encounter is too short") ?? false)
800802
{
801803
AddToText(">:> Encounter is too short to generate a valid log, the upload try will not be automatically reuploaded.");
802-
LogReuploader.RemovedLogAndSave(file);
804+
LogReuploader.RemoveLogAndSave(file);
803805
return;
804806
}
805807
}
@@ -827,7 +829,7 @@ private async Task HttpUploadLogAsync(string file, Dictionary<string, string> po
827829
}
828830
LogReuploader.FailedLogs.Add(file);
829831
LogReuploader.SaveFailedLogs();
830-
EnsureReuploadTimerStart();
832+
EnsureReuploadAndRePingTimerStart();
831833
return;
832834
}
833835
AddToText($">:> Unable to upload file {Path.GetFileName(file)}, dps.report responded with an non-ok status code ({(int)responseMessage.StatusCode}).");
@@ -924,7 +926,7 @@ private async Task HttpUploadLogAsync(string file, Dictionary<string, string> po
924926
// report success
925927
AddToText($">:> {Path.GetFileName(file)} successfully uploaded.");
926928
// remove from failed logs if present
927-
LogReuploader.RemovedLogAndSave(file);
929+
LogReuploader.RemoveLogAndSave(file);
928930
}
929931
catch (Exception e)
930932
{
@@ -954,7 +956,7 @@ private async Task HandleQuickLogUploadRetry(string file, Dictionary<string, str
954956
AddToText($">:> Upload retry failed 4 times for {Path.GetFileName(file)}, will try again during log reupload timer.");
955957
LogReuploader.FailedLogs.Add(file);
956958
LogReuploader.SaveFailedLogs();
957-
EnsureReuploadTimerStart();
959+
EnsureReuploadAndRePingTimerStart();
958960
}
959961
else
960962
{
@@ -984,11 +986,7 @@ private async Task ExecuteAllDiscordWebhooks(DpsReportJson reportJson, List<LogP
984986
{
985987
if (logSessionLink.SessionRunning)
986988
{
987-
if (logSessionLink.checkBoxOnlySuccess.Checked && (reportJson.Encounter.Success ?? false))
988-
{
989-
SessionLogs.Add(reportJson);
990-
}
991-
else if (!logSessionLink.checkBoxOnlySuccess.Checked)
989+
if ((logSessionLink.checkBoxOnlySuccess.Checked && (reportJson.Encounter.Success ?? false)) || !logSessionLink.checkBoxOnlySuccess.Checked)
992990
{
993991
SessionLogs.Add(reportJson);
994992
}
@@ -1045,7 +1043,23 @@ private async Task CrossUploadToWingman(string file, DpsReportJsonExtraJson extr
10451043
{
10461044
return;
10471045
}
1048-
AddToText(await Gw2WingmanUploader.Upload(file, extraJson));
1046+
var resultText = await Gw2WingmanUploader.Upload(file, extraJson);
1047+
if (resultText.Contains("fail") && !resultText.Contains("exists"))
1048+
{
1049+
WingmanRePing.LogsToPing.Add(new WingmanPingInfo
1050+
{
1051+
FilePath = file,
1052+
TriggerId = extraJson.TriggerId,
1053+
UploadedBy = extraJson.RecordedByAccountName,
1054+
});
1055+
WingmanRePing.SaveLogsToPing();
1056+
EnsureReuploadAndRePingTimerStart();
1057+
}
1058+
else
1059+
{
1060+
WingmanRePing.RemoveLogAndSave(file);
1061+
}
1062+
AddToText(resultText);
10491063
}
10501064

10511065
internal bool IsTwitchConnectionNull() => chatConnect is null;
@@ -1706,18 +1720,19 @@ private void TimerCheckUpdate_Elapsed(object sender, EventArgs e)
17061720
_ = NewReleaseCheckAsync(false, true);
17071721
}
17081722

1709-
private void TimerFailedLogsReupload_Elapsed(object sender, EventArgs e)
1723+
private void TimerFailedLogsReuploadAndRePingElapsed(object sender, EventArgs e)
17101724
{
17111725
HandleLogReuploads();
1726+
HandleWingmanRePings();
17121727
}
17131728

1714-
private void EnsureReuploadTimerStart()
1729+
private void EnsureReuploadAndRePingTimerStart()
17151730
{
1716-
if (timerFailedLogsReupload.Enabled)
1731+
if (timerFailedLogsReuploadAndRePing.Enabled)
17171732
{
17181733
return;
17191734
}
1720-
timerFailedLogsReupload.Start();
1735+
timerFailedLogsReuploadAndRePing.Start();
17211736
}
17221737

17231738
private void HandleLogReuploads()
@@ -1731,6 +1746,17 @@ private void HandleLogReuploads()
17311746
AddToText(">:> Log reuploading has ended.");
17321747
}
17331748

1749+
private void HandleWingmanRePings()
1750+
{
1751+
if (WingmanRePing.LogsToPing.Count == 0)
1752+
{
1753+
return;
1754+
}
1755+
AddToText($">:> Starting wingman re-pings of {WingmanRePing.LogsToPing.Count} logs...");
1756+
WingmanRePing.ProcessLogs(semaphore, CrossUploadToWingman);
1757+
AddToText(">:> Wingman re-pings has been completed.");
1758+
}
1759+
17341760
private void ComboBoxMaxUploads_SelectedIndexChanged(object sender, EventArgs e)
17351761
{
17361762
if (!int.TryParse(comboBoxMaxUploads.Text, out var threads))

Tools/LogReuploader.cs

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using System;
33
using System.Collections.Generic;
44
using System.IO;
5-
using System.Linq;
65
using System.Threading;
76
using System.Threading.Tasks;
87
using ZLinq;
@@ -24,24 +23,28 @@ internal static HashSet<string> FailedLogs
2423
{
2524
get
2625
{
27-
if (_failedLogs is null)
26+
if (_failedLogs is not null)
2827
{
29-
if (File.Exists(FileLocation))
28+
return _failedLogs;
29+
}
30+
if (File.Exists(FileLocation))
31+
{
32+
try
3033
{
31-
try
32-
{
33-
_failedLogs = File.ReadAllLines(FileLocation).Where(File.Exists).ToHashSet();
34-
}
35-
catch
36-
{
37-
_failedLogs = [];
38-
}
34+
_failedLogs = File.ReadAllLines(FileLocation)
35+
.AsValueEnumerable()
36+
.Where(File.Exists)
37+
.ToHashSet();
3938
}
40-
else
39+
catch
4140
{
4241
_failedLogs = [];
4342
}
4443
}
44+
else
45+
{
46+
_failedLogs = [];
47+
}
4548
return _failedLogs;
4649
}
4750
}
@@ -58,7 +61,7 @@ internal static void SaveFailedLogs()
5861
}
5962
}
6063

61-
internal static bool RemovedLogAndSave(string file)
64+
internal static bool RemoveLogAndSave(string file)
6265
{
6366
var removed = FailedLogs.Remove(file);
6467
if (removed)
@@ -70,7 +73,7 @@ internal static bool RemovedLogAndSave(string file)
7073

7174
internal static void ProcessLogs(SemaphoreSlim semaphore, Func<string, Dictionary<string, string>, bool, Task> process)
7275
{
73-
foreach (var fileName in FailedLogs.ToArray().AsValueEnumerable())
76+
foreach (var fileName in FailedLogs.AsValueEnumerable())
7477
{
7578
if (!File.Exists(fileName))
7679
{
@@ -79,7 +82,7 @@ internal static void ProcessLogs(SemaphoreSlim semaphore, Func<string, Dictionar
7982
}
8083
_ = Task.Run(async () =>
8184
{
82-
semaphore.Wait();
85+
await semaphore.WaitAsync();
8386
await process(fileName, PostData, true);
8487
semaphore.Release();
8588
});

Tools/WingmanPingInfo.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using Newtonsoft.Json;
2+
3+
namespace PlenBotLogUploader.Tools;
4+
5+
public sealed class WingmanPingInfo
6+
{
7+
[JsonProperty("filePath")]
8+
internal string FilePath { get; set; }
9+
10+
[JsonProperty("triggerID")]
11+
internal int TriggerId { get; set; }
12+
13+
[JsonProperty("uploadedBy")]
14+
internal string UploadedBy { get; set; }
15+
}

Tools/WingmanRePing.cs

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
using Newtonsoft.Json;
2+
using PlenBotLogUploader.AppSettings;
3+
using PlenBotLogUploader.DpsReport;
4+
using System;
5+
using System.Collections.Generic;
6+
using System.IO;
7+
using System.Threading;
8+
using System.Threading.Tasks;
9+
using ZLinq;
10+
11+
namespace PlenBotLogUploader.Tools;
12+
13+
public static class WingmanRePing
14+
{
15+
private static readonly string FileLocation = $@"{ApplicationSettings.LocalDir}\wingmanreping.json";
16+
17+
private static HashSet<WingmanPingInfo> _logsToPing;
18+
19+
internal static HashSet<WingmanPingInfo> LogsToPing
20+
{
21+
get
22+
{
23+
if (_logsToPing is not null)
24+
{
25+
return _logsToPing;
26+
}
27+
if (File.Exists(FileLocation))
28+
{
29+
try
30+
{
31+
_logsToPing = JsonConvert.DeserializeObject<List<WingmanPingInfo>>(File.ReadAllText(FileLocation))
32+
.AsValueEnumerable()
33+
.Where(x => File.Exists(x.FilePath))
34+
.ToHashSet();
35+
}
36+
catch
37+
{
38+
_logsToPing = [];
39+
}
40+
}
41+
else
42+
{
43+
_logsToPing = [];
44+
}
45+
return _logsToPing;
46+
}
47+
}
48+
49+
internal static void SaveLogsToPing()
50+
{
51+
try
52+
{
53+
File.WriteAllText(FileLocation, JsonConvert.SerializeObject(LogsToPing, Formatting.Indented));
54+
}
55+
catch
56+
{
57+
// do nothing
58+
}
59+
}
60+
61+
internal static void RemoveLogAndSave(string file)
62+
{
63+
var logToRemove = LogsToPing
64+
.AsValueEnumerable()
65+
.FirstOrDefault(x => file.Equals(x.FilePath) && File.Exists(x.FilePath));
66+
if (logToRemove is null)
67+
{
68+
return;
69+
}
70+
var removed = LogsToPing.Remove(logToRemove);
71+
if (removed)
72+
{
73+
SaveLogsToPing();
74+
}
75+
return;
76+
}
77+
78+
internal static void ProcessLogs(SemaphoreSlim semaphore, Func<string, DpsReportJsonExtraJson, Task> process)
79+
{
80+
foreach (var wingmanPingInfo in LogsToPing.AsValueEnumerable())
81+
{
82+
if (!File.Exists(wingmanPingInfo.FilePath))
83+
{
84+
LogsToPing.Remove(wingmanPingInfo);
85+
continue;
86+
}
87+
_ = Task.Run(async () =>
88+
{
89+
var convertedExtraJson = new DpsReportJsonExtraJson()
90+
{
91+
TriggerId = wingmanPingInfo.TriggerId,
92+
RecordedByAccountName = wingmanPingInfo.UploadedBy,
93+
};
94+
await semaphore.WaitAsync();
95+
await process(wingmanPingInfo.FilePath, convertedExtraJson);
96+
semaphore.Release();
97+
});
98+
}
99+
}
100+
}

0 commit comments

Comments
 (0)