diff --git a/Models/AppSettings.cs b/Models/AppSettings.cs index ce7412f..a376a4d 100644 --- a/Models/AppSettings.cs +++ b/Models/AppSettings.cs @@ -22,6 +22,16 @@ static Settings() /// public string? DataLocation { get; set; } + /// + /// Discord WebHook URL for backups. + /// + public string? DiscordWebhookURL { get; set; } + + /// + /// Discord WebHook backups toggle state. + /// + public bool DiscordWebhookEnabled { get; set; } + /// /// Automatically copy newly detected save codes as you play. /// diff --git a/Models/Entry.cs b/Models/Entry.cs index 24d48a2..001519c 100644 --- a/Models/Entry.cs +++ b/Models/Entry.cs @@ -34,12 +34,16 @@ internal class Entry public DateTime Timestamp; public string Content; + [JsonProperty("pc")] + public int PlayerCount; public string? Players; public string[]? RTerrors; public string? RType; + public ToNRoundType RT; public ToNRoundResult RResult; + [JsonIgnore] public History? Parent; [JsonIgnore] public bool Fresh; [JsonIgnore] public int Length => Content.Length; @@ -58,7 +62,7 @@ public override string ToString() if (Settings.Get.SaveRoundInfo && Settings.Get.ShowWinLose) { sb.Append('['); - sb.Append(RResult == ToNRoundResult.R ? ' ' : RResult.ToString()); + sb.Append(RResult); sb.Append("] "); } @@ -73,11 +77,11 @@ public override string ToString() return sb.ToString(); } - public string GetTooltip(bool showPlayers, bool showTerrors) + public string GetTooltip(bool showPlayers, bool showTerrors, bool showNote = true) { StringBuilder sb = new StringBuilder(); sb.Append(Timestamp.ToString("F")); - if (!string.IsNullOrEmpty(Note)) + if (!string.IsNullOrEmpty(Note) && showNote) { sb.AppendLine(); sb.AppendLine(); @@ -89,7 +93,7 @@ public string GetTooltip(bool showPlayers, bool showTerrors) sb.AppendLine(); sb.AppendLine(); - sb.AppendLine("Round info: " + (RResult == ToNRoundResult.W ? "Survived" : "Died")); + // sb.AppendLine("Round info: " + (RResult == ToNRoundResult.W ? "Survived" : "Died")); if (!string.IsNullOrEmpty(RType)) sb.AppendLine("Round type: " + RType); diff --git a/Models/History.cs b/Models/History.cs index 8d75a90..b957e1d 100644 --- a/Models/History.cs +++ b/Models/History.cs @@ -1,6 +1,8 @@ using Newtonsoft.Json; using System.Globalization; +using LogContext = ToNSaveManager.Utils.LogWatcher.LogContext; + namespace ToNSaveManager.Models { internal class History : IComparable @@ -10,6 +12,8 @@ internal class History : IComparable public DateTime Timestamp = DateTime.MinValue; public bool IsCustom = false; + public string? DisplayName = string.Empty; + [JsonConstructor] private History() { } @@ -27,6 +31,11 @@ public History(string name, DateTime timestamp) IsCustom = true; } + public void SetLogContext(LogContext context) + { + DisplayName = context.DisplayName; + } + public void SetLogKey(string logKey) { if (IsCustom) return; diff --git a/Models/ToNIndex.cs b/Models/ToNIndex.cs index 6f18015..35f8e6b 100644 --- a/Models/ToNIndex.cs +++ b/Models/ToNIndex.cs @@ -1,4 +1,4 @@ -using System.Diagnostics; +using Newtonsoft.Json; namespace ToNSaveManager.Models { @@ -93,6 +93,9 @@ public string GetNames(string separator = ", ") "RUN" , "走れ!", // The meatball man "8 Pages" , "8ページ", + // Events + "Cold Night" , "冷たい夜", // Winterfest + // Beyond's favorite "Custom" , "カスタム", // IGNORE SAVES FOR THIS ONE }; @@ -115,13 +118,40 @@ static ToNRoundType GetRoundType(string raw) raw = raw.Replace(' ', '_').Replace("8", "Eight"); return Enum.TryParse(typeof(ToNRoundType), raw, out object? result) && result != null ? (ToNRoundType)result : ToNRoundType.Unknown; } + + internal static uint GetRoundColorFromType(ToNRoundType RoundType) => RoundTypeColors.ContainsKey(RoundType) ? RoundTypeColors[RoundType] : 16721714; + + internal static readonly Dictionary RoundTypeColors = new Dictionary() + { + { ToNRoundType.Unknown, 16721714 }, + { ToNRoundType.Classic, 0xFFFFFF }, + { ToNRoundType.Fog, 0x808486 }, + { ToNRoundType.Punished, 0xFFF800 }, + { ToNRoundType.Sabotage, 0x3BF37D }, + { ToNRoundType.Cracked, 0xFF00D3 }, + { ToNRoundType.Bloodbath, 0xF51313 }, + + { ToNRoundType.Midnight, 0xE23232 }, + { ToNRoundType.Alternate, 0xF1F1F1 }, + + { ToNRoundType.Mystic_Moon, 0xB0DEF9 }, + { ToNRoundType.Twilight, 0xF8A900 }, + { ToNRoundType.Blood_Moon, 0xF51313 }, + { ToNRoundType.Solstice, 0x3BF3B3 }, + + { ToNRoundType.RUN, 0xC15E3D }, + { ToNRoundType.Eight_Pages, 0xFFFFFF }, + { ToNRoundType.Custom, 0x000000 }, // Ignored + + { ToNRoundType.Cold_Night, 0xA37BE4 }, + }; } public enum ToNRoundResult { R, // Respawn W, // Win - L, // Lose + D, // Leaving } public enum ToNRoundType @@ -140,7 +170,10 @@ public enum ToNRoundType Mystic_Moon, Blood_Moon, Twilight, Solstice, // Special // Replace 8 with Eight - RUN, Eight_Pages, Custom + RUN, Eight_Pages, Custom, + + // Events + Cold_Night } internal class ToNIndex diff --git a/README.md b/README.md index 9c0d655..3f58af8 100644 --- a/README.md +++ b/README.md @@ -26,10 +26,11 @@ - `Auto Clipboard Copy` Automatically copy new save codes to clipboard. - `Collect Player Names` Save codes will show players that were in the instance. - `XSOverlay Popup` XSOverlay notifications when new save codes are detected. -- `Play Audio` Play a notification audio when a new save is detected. +- `Play Sound` Play a notification audio when a new save is detected. - Double Click to select a custom audio file. (Only '.wav' files) - Right Click to reset audio file back to 'default.wav' - `Colorful Objectives` Items in the 'Objectives' window will show colors that correspond to those of the items in the game. +- `Auto Discord Backup` Uses a [discord webhook](##how-to-properly-configure-automatic-discord-backup-using-webhooks) to automatically upload a backup of your new codes to a discord channel as you play. - `Check For Updates` When clicked, it will check this github repo for new releases, and prompt you to try an automatic update.
Preview Image

@@ -41,6 +42,7 @@ - ### Save Codes (Right Panel) * `Add to` Lets you save or favorite this code to a separated custom collection with a name of your choice. * `Edit Note` You can attach a note to this save code, so you can recognize it better. + * `Backup` Forces a backup upload to Discord if **Auto Discord Backup** is configured on settings. * `Delete` Deletes just this save code from the database. ### Objectives Window @@ -71,6 +73,26 @@ >

> +> ## How to properly configure Automatic Discord Backup using Webhooks? +> You can set a Discord webhook url to automatically upload your codes to a discord channel. +> +> - Just go to your preferred channel on your discord server. +> - Click **Edit Channel** and then go to **Integrations**. +> - Add a webhook integration to this channel. *You can give it a name and a profile picture*. +> - Copy the webhook url. +> - Open settings on the Save Manager app. +> - Enable `Auto Discord Backup`, you will see a text input popup. +> - Paste your webhook url in the text field. +> - Click **save**. +> +> NOTE: If you want to test this functionality, you can right click on a save entry then click **Backup**. If everything is right, save will be uploaded to the discord channel. +>
+> Show Discord Screenshots +>

+>

+>

+>
+ > ## Why is the .exe so big? >100MB > The exe is bundled with the .NET runtime that it's required to run the program. Using a command line argument for dotnet publishing: `--self-contained true -p:PublishSingleFile=true`
> This adds size to the file, but ensures that the program runs independently without relying on a previous .NET installation. @@ -87,8 +109,14 @@ > We are allowed to read these files since it does not modify or alter the game in any way. > **This is not a mod or a cheat.** +> ### Please do NOT message Beyond about suggestions or problems with this tool. +> You can report problems or suggestions under the [Issues](https://github.com/ChrisFeline/ToNSaveManager/issues) tab on this repo. Alternatively see contact information below. + # 📫 Contact: > **Discord:** [@Kittenji](https://discord.gg/HGk2RQX)
> **VRChat:** [Kittenji](https://vrchat.com/home/user/usr_7ac745b8-e50e-4c9c-95e5-8e7e3bcde682) > ## Say hi if you see me playing [Terrors of Nowhere](https://vrchat.com/home/world/wrld_a61cdabe-1218-4287-9ffc-2a4d1414e5bd)! ->

Preview

\ No newline at end of file +>

Preview

+ +# ❤️ Support: +> If you want to support the development of this tool you can [Buy Me A Coffee ♥](https://ko-fi.com/kittenji) on ko-fi. \ No newline at end of file diff --git a/Resources/Webhook/screenshot_0.png b/Resources/Webhook/screenshot_0.png new file mode 100644 index 0000000..0f064cd Binary files /dev/null and b/Resources/Webhook/screenshot_0.png differ diff --git a/Resources/Webhook/screenshot_1.png b/Resources/Webhook/screenshot_1.png new file mode 100644 index 0000000..b47563e Binary files /dev/null and b/Resources/Webhook/screenshot_1.png differ diff --git a/Resources/Webhook/screenshot_2.png b/Resources/Webhook/screenshot_2.png new file mode 100644 index 0000000..f25c298 Binary files /dev/null and b/Resources/Webhook/screenshot_2.png differ diff --git a/Resources/settings.png b/Resources/settings.png index aac8c0d..a6ac865 100644 Binary files a/Resources/settings.png and b/Resources/settings.png differ diff --git a/Resources/support_icon.png b/Resources/support_icon.png new file mode 100644 index 0000000..126ce44 Binary files /dev/null and b/Resources/support_icon.png differ diff --git a/ToNSaveManager.csproj b/ToNSaveManager.csproj index 8c70228..ecc2ce3 100644 --- a/ToNSaveManager.csproj +++ b/ToNSaveManager.csproj @@ -52,4 +52,19 @@ + + + True + True + Resources.resx + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + \ No newline at end of file diff --git a/Utils/Discord/DSWebHook.cs b/Utils/Discord/DSWebHook.cs new file mode 100644 index 0000000..0c28e09 --- /dev/null +++ b/Utils/Discord/DSWebHook.cs @@ -0,0 +1,147 @@ +using System.Text; +using ToNSaveManager.Models; +using Newtonsoft.Json; +using System.Globalization; +using System.Text.RegularExpressions; + +namespace ToNSaveManager.Utils.Discord +{ + using Models; + + internal class Payload + { + [JsonProperty("embeds")] + public Embed[] Embeds = new Embed[1] { new Embed() }; + + [JsonIgnore] + public Embed Embed => Embeds[0]; + } + + internal static class DSWebHook + { + static Entry? LastEntry; + + static readonly Embed[] Embeds = new Embed[1]; + + static readonly Payload PayloadData = new Payload(); + static Embed EmbedData => PayloadData.Embed; + + static readonly JsonSerializerSettings JsonSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }; + + static readonly Queue EntryQueue = new Queue(); + static bool IsSending = false; + + internal static void Send(Entry entry, bool ignoreDuplicate = false) + { + if (!Settings.Get.DiscordWebhookEnabled) return; + + string? webhookUrl = Settings.Get.DiscordWebhookURL; + if (string.IsNullOrEmpty(webhookUrl)) return; + + if (!ignoreDuplicate && LastEntry != null && LastEntry.Content == entry.Content) return; + LastEntry = entry; + + EntryQueue.Enqueue(entry); + if (IsSending) return; + + _ = Send(webhookUrl); + } + + private static async Task Send(string webhookUrl) + { + IsSending = true; + + try + { + using (HttpClient httpClient = new HttpClient()) + { + while (EntryQueue.Count > 0) + { + Entry entry = EntryQueue.Dequeue(); + DateTime time = entry.Timestamp; + + if (EmbedData.Footer == null) + { + EmbedData.Footer = new EmbedFooter() + { + IconUrl = "https://github.com/ChrisFeline/ToNSaveManager/blob/main/Resources/xs_icon.png?raw=true", + ProxyIconUrl = "https://github.com/ChrisFeline/ToNSaveManager/blob/main/Resources/xs_icon.png?raw=true", + Text = "Terrors of Nowhere: Save Manager" + }; + } + + EmbedData.Description = string.Empty; + EmbedData.Timestamp = time; + EmbedData.Color = TerrorMatrix.GetRoundColorFromType(entry.RT); + + if (entry.Parent != null && !string.IsNullOrEmpty(entry.Parent.DisplayName)) + { + // if (EmbedData.Description.Length > 0) EmbedData.Description += "\n"; + EmbedData.Description += "**Username**: `" + entry.Parent.DisplayName + "`"; + } + + if (!string.IsNullOrEmpty(entry.RType)) + { + if (EmbedData.Description.Length > 0) EmbedData.Description += "\n"; + EmbedData.Description += "**Round Type**: `" + entry.RType + "`"; + } + + if (entry.RTerrors != null && entry.RTerrors.Length > 0) + { + if (EmbedData.Description.Length > 0) EmbedData.Description += "\n"; + EmbedData.Description += "**Terrors in Round**: `" + string.Join("`, `", entry.RTerrors) + "`"; + } + + if (entry.PlayerCount > 0) + { + if (EmbedData.Description.Length > 0) EmbedData.Description += "\n"; + EmbedData.Description += $"**Player Count**: `{entry.PlayerCount}`"; + } + + string payloadData = JsonConvert.SerializeObject(PayloadData, JsonSettings); + + MultipartFormDataContent form = new MultipartFormDataContent(); + // Append file data + byte[] data = Encoding.Default.GetBytes(entry.Content); + form.Add(new ByteArrayContent(data, 0, data.Length), "Document", $"TON_BACKUP_{time.Year}_{time.Month}_{time.Day}_{time.Hour.ToString("00")}{time.Minute.ToString("00")}{time.Second.ToString("00")}.txt"); + // Append json + form.Add(new StringContent(payloadData, Encoding.UTF8, "application/json"), "payload_json"); + _ = await httpClient.PostAsync(webhookUrl, form); + + // Wait a second before send the next message + if (EntryQueue.Count > 0) await Task.Delay(1000); + } + } + } + catch (Exception) { } + + IsSending = false; + } + + #region Validation + private static Regex WebhookUrlRegex = new Regex(@"^.*(discord|discordapp)\.com\/api\/webhooks\/([\d]+)\/([a-z0-9_-]+)$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + + internal static bool ValidateURL(string webhookUrl) + { + if (string.IsNullOrWhiteSpace(webhookUrl)) + return false; + + Match match = WebhookUrlRegex.Match(webhookUrl); + if (match != null) + { + // ensure that the first group is a ulong, set the _webhookId + // 0th group is always the entire match, and 1 is the domain; so start at index 2 + if (!(match.Groups[2].Success && ulong.TryParse(match.Groups[2].Value, NumberStyles.None, CultureInfo.InvariantCulture, out ulong webhookId)) || webhookId == 0) + return false; + + if (!match.Groups[3].Success) + return false; + + return true; + } + + return false; + } + #endregion + } +} diff --git a/Utils/Discord/Models/Embed.cs b/Utils/Discord/Models/Embed.cs new file mode 100644 index 0000000..140e239 --- /dev/null +++ b/Utils/Discord/Models/Embed.cs @@ -0,0 +1,45 @@ +using Newtonsoft.Json; + +namespace ToNSaveManager.Utils.Discord.Models +{ + internal class Embed + { + [JsonProperty("title")] + public string? Title { get; set; } + + [JsonProperty("description")] + public string? Description { get; set; } + + [JsonProperty("url")] + public string? Url { get; set; } + + [JsonProperty("color")] + public uint Color { get; set; } = 16721714; + + [JsonProperty("timestamp")] + public DateTimeOffset? Timestamp { get; set; } + + [JsonProperty("footer")] + public EmbedFooter? Footer { get; set; } + + /* + [JsonProperty("author")] + public EmbedAuthor Author { get; set; } + + [JsonProperty("video")] + public EmbedVideo Video { get; set; } + + [JsonProperty("thumbnail")] + public EmbedThumbnail Thumbnail { get; set; } + + [JsonProperty("image")] + public EmbedImage Image { get; set; } + + [JsonProperty("provider")] + public EmbedProvider Provider { get; set; } + + [JsonProperty("fields")] + public EmbedField[] Fields { get; set; } + */ + } +} diff --git a/Utils/Discord/Models/EmbedFooter.cs b/Utils/Discord/Models/EmbedFooter.cs new file mode 100644 index 0000000..9f4bbfd --- /dev/null +++ b/Utils/Discord/Models/EmbedFooter.cs @@ -0,0 +1,16 @@ +using Newtonsoft.Json; + +namespace ToNSaveManager.Utils.Discord.Models +{ + internal class EmbedFooter + { + [JsonProperty("text")] + public string? Text { get; set; } + + [JsonProperty("icon_url")] + public string? IconUrl { get; set; } + + [JsonProperty("proxy_icon_url")] + public string? ProxyIconUrl { get; set; } + } +} diff --git a/Utils/LogWatcher.cs b/Utils/LogWatcher.cs index f239902..61ce6b2 100644 --- a/Utils/LogWatcher.cs +++ b/Utils/LogWatcher.cs @@ -107,7 +107,7 @@ private void LogTick(object? sender, EventArgs? e) } if (SkipParsedLogs) - SetParsedPos(logContext.DateKey, logContext.Position, firstRun); + SetParsedPos(logContext.DateKey, isOlder ? logContext.Position : logContext.RoomReadPos, firstRun); } } @@ -246,6 +246,8 @@ private bool ParseLocation(string line, DateTime lineDate, LogContext logContext var worldName = line.Substring(index).Trim('\n', '\r'); logContext.Enter(worldName, lineDate); + logContext.RoomReadPos = logContext.Position; + return true; } @@ -299,6 +301,7 @@ public class LogContext public string? DisplayName; // Recent Instance info + public long RoomReadPos { get; set; } public string? RoomName { get; private set; } public DateTime RoomDate { get; private set; } public readonly HashSet Players; diff --git a/Windows/EditWindow.cs b/Windows/EditWindow.cs index ecefb79..250b939 100644 --- a/Windows/EditWindow.cs +++ b/Windows/EditWindow.cs @@ -8,7 +8,7 @@ public struct EditResult public partial class EditWindow : Form { - static readonly EditWindow Instance = new EditWindow(); + static EditWindow Instance = new EditWindow(); public static Size GetSize() => Instance.Size; string Content @@ -24,6 +24,8 @@ private EditWindow() public static EditResult Show(string content, string title, Form parent) { + if (Instance.IsDisposed) Instance = new EditWindow(); + Instance.Text = title; Instance.Owner = parent; Instance.StartPosition = FormStartPosition.CenterParent; diff --git a/Windows/MainWindow.Designer.cs b/Windows/MainWindow.Designer.cs index 4af7e69..5500cd2 100644 --- a/Windows/MainWindow.Designer.cs +++ b/Windows/MainWindow.Designer.cs @@ -36,6 +36,7 @@ private void InitializeComponent() ctxMenuEntriesCopyTo = new ToolStripMenuItem(); ctxMenuEntriesNew = new ToolStripMenuItem(); ctxMenuEntriesNote = new ToolStripMenuItem(); + ctxMenuEntriesBackup = new ToolStripMenuItem(); toolStripMenuItem2 = new ToolStripSeparator(); ctxMenuEntriesDelete = new ToolStripMenuItem(); ctxMenuKeys = new ContextMenuStrip(components); @@ -47,6 +48,7 @@ private void InitializeComponent() button1 = new Button(); button2 = new Button(); splitContainer1 = new SplitContainer(); + linkSupport = new Button(); ctxMenuEntries.SuspendLayout(); ctxMenuKeys.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)splitContainer1).BeginInit(); @@ -98,9 +100,9 @@ private void InitializeComponent() // // ctxMenuEntries // - ctxMenuEntries.Items.AddRange(new ToolStripItem[] { ctxMenuEntriesCopyTo, ctxMenuEntriesNote, toolStripMenuItem2, ctxMenuEntriesDelete }); + ctxMenuEntries.Items.AddRange(new ToolStripItem[] { ctxMenuEntriesCopyTo, ctxMenuEntriesNote, ctxMenuEntriesBackup, toolStripMenuItem2, ctxMenuEntriesDelete }); ctxMenuEntries.Name = "ctxMenuEntries"; - ctxMenuEntries.Size = new Size(138, 76); + ctxMenuEntries.Size = new Size(181, 120); ctxMenuEntries.Closed += ctxMenuEntries_Closed; ctxMenuEntries.Opened += ctxMenuEntries_Opened; // @@ -108,13 +110,13 @@ private void InitializeComponent() // ctxMenuEntriesCopyTo.DropDownItems.AddRange(new ToolStripItem[] { ctxMenuEntriesNew }); ctxMenuEntriesCopyTo.Name = "ctxMenuEntriesCopyTo"; - ctxMenuEntriesCopyTo.Size = new Size(137, 22); + ctxMenuEntriesCopyTo.Size = new Size(180, 22); ctxMenuEntriesCopyTo.Text = "Add to"; // // ctxMenuEntriesNew // ctxMenuEntriesNew.Name = "ctxMenuEntriesNew"; - ctxMenuEntriesNew.Size = new Size(172, 22); + ctxMenuEntriesNew.Size = new Size(155, 22); ctxMenuEntriesNew.Text = "New Collection"; ctxMenuEntriesNew.ToolTipText = "Add this entry to a new collection."; ctxMenuEntriesNew.Click += ctxMenuEntriesNew_Click; @@ -122,19 +124,28 @@ private void InitializeComponent() // ctxMenuEntriesNote // ctxMenuEntriesNote.Name = "ctxMenuEntriesNote"; - ctxMenuEntriesNote.Size = new Size(137, 22); + ctxMenuEntriesNote.Size = new Size(180, 22); ctxMenuEntriesNote.Text = "Edit Note"; ctxMenuEntriesNote.Click += ctxMenuEntriesNote_Click; // + // ctxMenuEntriesBackup + // + ctxMenuEntriesBackup.Enabled = false; + ctxMenuEntriesBackup.Name = "ctxMenuEntriesBackup"; + ctxMenuEntriesBackup.Size = new Size(180, 22); + ctxMenuEntriesBackup.Text = "Backup"; + ctxMenuEntriesBackup.ToolTipText = "Force upload a backup of this code to Discord as a file, requires Auto Discord Backup to be enabled in settings."; + ctxMenuEntriesBackup.Click += ctxMenuEntriesBackup_Click; + // // toolStripMenuItem2 // toolStripMenuItem2.Name = "toolStripMenuItem2"; - toolStripMenuItem2.Size = new Size(134, 6); + toolStripMenuItem2.Size = new Size(177, 6); // // ctxMenuEntriesDelete // ctxMenuEntriesDelete.Name = "ctxMenuEntriesDelete"; - ctxMenuEntriesDelete.Size = new Size(137, 22); + ctxMenuEntriesDelete.Size = new Size(180, 22); ctxMenuEntriesDelete.Text = "Delete"; ctxMenuEntriesDelete.Click += ctxMenuEntriesDelete_Click; // @@ -142,31 +153,31 @@ private void InitializeComponent() // ctxMenuKeys.Items.AddRange(new ToolStripItem[] { importToolStripMenuItem, renameToolStripMenuItem, toolStripMenuItem1, deleteToolStripMenuItem }); ctxMenuKeys.Name = "ctxMenuKeys"; - ctxMenuKeys.Size = new Size(117, 76); + ctxMenuKeys.Size = new Size(118, 76); // // importToolStripMenuItem // importToolStripMenuItem.Name = "importToolStripMenuItem"; - importToolStripMenuItem.Size = new Size(116, 22); + importToolStripMenuItem.Size = new Size(117, 22); importToolStripMenuItem.Text = "Import"; importToolStripMenuItem.Click += ctxMenuKeysImport_Click; // // renameToolStripMenuItem // renameToolStripMenuItem.Name = "renameToolStripMenuItem"; - renameToolStripMenuItem.Size = new Size(116, 22); + renameToolStripMenuItem.Size = new Size(117, 22); renameToolStripMenuItem.Text = "Rename"; renameToolStripMenuItem.Click += ctxMenuKeysRename_Click; // // toolStripMenuItem1 // toolStripMenuItem1.Name = "toolStripMenuItem1"; - toolStripMenuItem1.Size = new Size(113, 6); + toolStripMenuItem1.Size = new Size(114, 6); // // deleteToolStripMenuItem // deleteToolStripMenuItem.Name = "deleteToolStripMenuItem"; - deleteToolStripMenuItem.Size = new Size(116, 22); + deleteToolStripMenuItem.Size = new Size(117, 22); deleteToolStripMenuItem.Text = "Delete"; deleteToolStripMenuItem.Click += ctxMenuKeysDelete_Click; // @@ -195,7 +206,7 @@ private void InitializeComponent() button1.ForeColor = Color.White; button1.Location = new Point(0, 223); button1.Name = "button1"; - button1.Size = new Size(259, 24); + button1.Size = new Size(229, 24); button1.TabIndex = 0; button1.TabStop = false; button1.Text = "Objectives"; @@ -209,7 +220,7 @@ private void InitializeComponent() button2.FlatAppearance.BorderColor = Color.FromArgb(122, 122, 122); button2.FlatStyle = FlatStyle.Flat; button2.ForeColor = Color.White; - button2.Location = new Point(265, 223); + button2.Location = new Point(235, 223); button2.Name = "button2"; button2.Size = new Size(58, 24); button2.TabIndex = 3; @@ -231,6 +242,7 @@ private void InitializeComponent() // // splitContainer1.Panel2 // + splitContainer1.Panel2.Controls.Add(linkSupport); splitContainer1.Panel2.Controls.Add(listBoxEntries); splitContainer1.Panel2.Controls.Add(button1); splitContainer1.Panel2.Controls.Add(button2); @@ -240,6 +252,22 @@ private void InitializeComponent() splitContainer1.TabStop = false; splitContainer1.SplitterMoved += splitContainer1_SplitterMoved; // + // linkSupport + // + linkSupport.Anchor = AnchorStyles.Bottom | AnchorStyles.Right; + linkSupport.BackColor = Color.FromArgb(46, 52, 64); + linkSupport.FlatAppearance.BorderColor = Color.FromArgb(122, 122, 122); + linkSupport.FlatStyle = FlatStyle.Flat; + linkSupport.ForeColor = Color.White; + linkSupport.Image = (Image)resources.GetObject("linkSupport.Image"); + linkSupport.Location = new Point(299, 223); + linkSupport.Name = "linkSupport"; + linkSupport.Size = new Size(24, 24); + linkSupport.TabIndex = 4; + linkSupport.TabStop = false; + linkSupport.UseVisualStyleBackColor = false; + linkSupport.Click += linkSupport_Click; + // // MainWindow // AutoScaleDimensions = new SizeF(7F, 15F); @@ -283,5 +311,7 @@ private void InitializeComponent() private Button button1; private Button button2; private SplitContainer splitContainer1; + private ToolStripMenuItem ctxMenuEntriesBackup; + private Button linkSupport; } } \ No newline at end of file diff --git a/Windows/MainWindow.cs b/Windows/MainWindow.cs index c5b0ed1..033e7d7 100644 --- a/Windows/MainWindow.cs +++ b/Windows/MainWindow.cs @@ -1,4 +1,4 @@ -using System.Diagnostics; +using System.Diagnostics; using System.Media; using ToNSaveManager.Extensions; using ToNSaveManager.Models; @@ -7,6 +7,7 @@ using OnLineArgs = ToNSaveManager.Utils.LogWatcher.OnLineArgs; using LogContext = ToNSaveManager.Utils.LogWatcher.LogContext; +using ToNSaveManager.Utils.Discord; namespace ToNSaveManager { @@ -60,6 +61,9 @@ private void mainWindow_Loaded(object sender, EventArgs e) this.Text = "Loading, please wait..."; XSOverlay.SetPort(Settings.Get.XSOverlayPort); + + SetBackupButton(Settings.Get.DiscordWebhookEnabled && !string.IsNullOrWhiteSpace(Settings.Get.DiscordWebhookURL)); + TooltipUtil.Set(linkSupport, "Buy Me A Coffee ♥"); } private void mainWindow_Shown(object sender, EventArgs e) @@ -280,7 +284,12 @@ private void ctxMenuEntries_Opened(object sender, EventArgs e) ctxMenuEntriesCopyTo.DropDownItems.Add(ctxMenuEntriesNew); if (listBoxEntries.SelectedItem == null) ctxMenuEntries.Close(); - else ContextEntry = (Entry)listBoxEntries.SelectedItem; + else + { + ContextEntry = (Entry)listBoxEntries.SelectedItem; + if (ContextEntry.Parent == null) + ContextEntry.Parent = (History?)listBoxKeys.SelectedItem; + } } private void ctxMenuEntriesNew_Click(object sender, EventArgs e) @@ -307,6 +316,14 @@ private void ctxMenuEntriesNote_Click(object sender, EventArgs e) listBoxEntries.SelectedIndex = -1; } + private void ctxMenuEntriesBackup_Click(object sender, EventArgs e) + { + if (ContextEntry != null) + DSWebHook.Send(ContextEntry, true); + + listBoxEntries.SelectedIndex = -1; + } + private void ctxMenuEntriesDelete_Click(object sender, EventArgs e) { if (listBoxKeys.SelectedItem == null) @@ -351,6 +368,12 @@ private void linkWiki_Clicked(object sender, EventArgs e) OpenExternalLink(wiki); } + private void linkSupport_Click(object sender, EventArgs e) + { + const string support = "https://ko-fi.com/kittenji"; + OpenExternalLink(support); + } + private void btnObjectives_Click(object sender, EventArgs e) { ObjectivesWindow.Open(this); @@ -459,6 +482,11 @@ internal static string GetTruncatedText(string text, Font font, int maxWidth) return text + "..."; } + + internal void SetBackupButton(bool enabled) + { + ctxMenuEntriesBackup.Enabled = enabled; + } #endregion #region Log Handling @@ -551,7 +579,7 @@ private bool HandleTerrorIndex(string line, DateTime timestamp, LogContext conte isOptedIn = line.StartsWith(ROUND_WON_KEYWORD); if (isOptedIn || line.StartsWith(ROUND_LOST_KEYWORD)) { - context.Set(ROUND_RESULT_KEY, isOptedIn ? ToNRoundResult.W : ToNRoundResult.L); + context.Set(ROUND_RESULT_KEY, isOptedIn ? ToNRoundResult.W : ToNRoundResult.D); return true; } @@ -627,13 +655,22 @@ private void AddLogEntry(string dateKey, string content, DateTime timestamp, Log if (collection == null) { collection = new History(dateKey); + collection.SetLogContext(context); AddKey(collection); } + if (string.IsNullOrEmpty(context.DisplayName) && !string.IsNullOrEmpty(collection.DisplayName)) + { + context.DisplayName = collection.DisplayName; + } + int ind = collection.Add(content, timestamp, out Entry? entry); if (ind < 0) return; // Not added, duplicate #pragma warning disable CS8604, CS8602 // Nullability is handled along with the return value of .Add + entry.PlayerCount = context.Players.Count; + entry.Parent = collection; + if (Settings.Get.SaveNames) entry.Players = context.GetRoomString(); if (Settings.Get.SaveRoundInfo) { @@ -652,6 +689,7 @@ private void AddLogEntry(string dateKey, string content, DateTime timestamp, Log { entry.RTerrors = killers.TerrorNames; entry.RType = killers.RoundTypeRaw; + entry.RT = killers.RoundType; if (Settings.Get.SaveRoundNote) entry.Note = string.Join(", ", killers.TerrorNames); @@ -672,6 +710,7 @@ private void AddLogEntry(string dateKey, string content, DateTime timestamp, Log { PlayNotification(); SendXSNotification(); + DSWebHook.Send(entry); } } diff --git a/Windows/MainWindow.resx b/Windows/MainWindow.resx index 12df1fd..7d1a689 100644 --- a/Windows/MainWindow.resx +++ b/Windows/MainWindow.resx @@ -18,7 +18,7 @@ System.Resources.ResXResourceReader, System.Windows.Forms, ... System.Resources.ResXResourceWriter, System.Windows.Forms, ... this is my long stringthis is a comment - Blue + Blue [base64 mime encoded serialized .NET Framework object] @@ -124,6 +124,21 @@ 175, 17 + + + iVBORw0KGgoAAAANSUhEUgAAAAsAAAAKCAYAAABi8KSDAAABgmlDQ1BJQ0MgcHJvZmlsZQAAKM+VkTlI + A0EYhT+jEhEvMIWI4BZqZRoVsQxRFEFBYgSvwt2NiUJ2E3YTbCwFW8HCo/EqbKy1tbAVBMEDxNrCStFG + wvrPRkgQIjgwzMebeY+ZNxA4TJuWWxMBy845sbGoNjs3rwVfCNJEC50EddPNTk6Pxqk4Pu+oUuttWGXx + v9GYWHZNqNKEI2bWyQkvCQ+u5bKKd4VD5oqeED4T7nXkgsIPSjeK/Ko45XNAZYaceGxYOCSspcrYKGNz + xbGEB4S7EpYt+YHZIicUryu20nnz557qhQ3L9sy00mV2MMY4k0yhYZBnlTQ5wrLaorjEZD9awd/u+6fE + ZYhrFVMcI2Sw0H0/6g9+d+sm+/uKSQ1RqH32vPduCG5DYcvzvo48r3AM1U9waZf8mUMY+hB9q6R1HUDz + BpxflTRjBy42oe0xqzu6L1XLDCST8HYq3zQHrTdQv1Ds7Wefk3uIS1cT17C3Dz0pyV6s8O668t7+POP3 + R/QbeWVyqQwXJNgAAAAJcEhZcwAACw0AAAsNAe0HwCwAAAAHdElNRQfoBw4QKSrn520hAAAAg0lEQVQo + U53M7QrCMAyF4V7lbLtVRfxAxtwQFMSLf03Tdm4/HLIDh5DyNGZVqN6weUH1RHfXgxukN93HRIB9CL7L + FGQ78K30CvVZevx+wMqFCFwBFwU0B5k7mWGCI/DxwimBZq+AUMM2NdMUvRDmQBv8HJZMwSIsUZhxflrO + 3/B3jPkAexOGRyThvYIAAAAASUVORK5CYII= + + AAABAAEAICAQAAEABADoAgAAFgAAACgAAAAgAAAAQAAAAAEABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA diff --git a/Windows/SettingsWindow.Designer.cs b/Windows/SettingsWindow.Designer.cs index dce424c..ca6f762 100644 --- a/Windows/SettingsWindow.Designer.cs +++ b/Windows/SettingsWindow.Designer.cs @@ -30,6 +30,7 @@ private void InitializeComponent() { components = new System.ComponentModel.Container(); groupBoxGeneral = new GroupBox(); + checkDiscordBackup = new CheckBox(); checkShowWinLose = new CheckBox(); checkSaveTerrorsNote = new CheckBox(); checkSaveTerrors = new CheckBox(); @@ -64,6 +65,7 @@ private void InitializeComponent() // groupBoxGeneral.AutoSize = true; groupBoxGeneral.AutoSizeMode = AutoSizeMode.GrowAndShrink; + groupBoxGeneral.Controls.Add(checkDiscordBackup); groupBoxGeneral.Controls.Add(checkShowWinLose); groupBoxGeneral.Controls.Add(checkSaveTerrorsNote); groupBoxGeneral.Controls.Add(checkSaveTerrors); @@ -74,29 +76,41 @@ private void InitializeComponent() groupBoxGeneral.ForeColor = Color.White; groupBoxGeneral.Location = new Point(8, 8); groupBoxGeneral.Name = "groupBoxGeneral"; - groupBoxGeneral.Size = new Size(268, 129); + groupBoxGeneral.Size = new Size(268, 148); groupBoxGeneral.TabIndex = 0; groupBoxGeneral.TabStop = false; groupBoxGeneral.Text = "General"; // + // checkDiscordBackup + // + checkDiscordBackup.Dock = DockStyle.Top; + checkDiscordBackup.Location = new Point(3, 127); + checkDiscordBackup.Name = "checkDiscordBackup"; + checkDiscordBackup.Padding = new Padding(3, 0, 3, 0); + checkDiscordBackup.Size = new Size(262, 18); + checkDiscordBackup.TabIndex = 6; + checkDiscordBackup.Tag = "DiscordWebhookEnabled|Automatically saves your new codes to a Discord channel using a webhook integration."; + checkDiscordBackup.Text = "Auto Discord Backup (Webhook)"; + checkDiscordBackup.UseVisualStyleBackColor = true; + // // checkShowWinLose // checkShowWinLose.Dock = DockStyle.Top; checkShowWinLose.ForeColor = Color.PowderBlue; - checkShowWinLose.Location = new Point(3, 108); + checkShowWinLose.Location = new Point(3, 109); checkShowWinLose.Name = "checkShowWinLose"; checkShowWinLose.Padding = new Padding(21, 0, 3, 0); checkShowWinLose.Size = new Size(262, 18); checkShowWinLose.TabIndex = 5; - checkShowWinLose.Tag = "ShowWinLose|Entries will show a [W] or [L] tag."; - checkShowWinLose.Text = "Show Win/Lose Tags"; + checkShowWinLose.Tag = "ShowWinLose|Entries will show a [R], [W] or [D] tag based on the source that triggered the save."; + checkShowWinLose.Text = "Show [R][W][D] Tags"; checkShowWinLose.UseVisualStyleBackColor = true; // // checkSaveTerrorsNote // checkSaveTerrorsNote.Dock = DockStyle.Top; checkSaveTerrorsNote.ForeColor = Color.PowderBlue; - checkSaveTerrorsNote.Location = new Point(3, 90); + checkSaveTerrorsNote.Location = new Point(3, 91); checkSaveTerrorsNote.Name = "checkSaveTerrorsNote"; checkSaveTerrorsNote.Padding = new Padding(21, 0, 3, 0); checkSaveTerrorsNote.Size = new Size(262, 18); @@ -108,7 +122,7 @@ private void InitializeComponent() // checkSaveTerrors // checkSaveTerrors.Dock = DockStyle.Top; - checkSaveTerrors.Location = new Point(3, 72); + checkSaveTerrors.Location = new Point(3, 73); checkSaveTerrors.Name = "checkSaveTerrors"; checkSaveTerrors.Padding = new Padding(3, 0, 3, 0); checkSaveTerrors.Size = new Size(262, 18); @@ -120,7 +134,7 @@ private void InitializeComponent() // checkPlayerNames // checkPlayerNames.Dock = DockStyle.Top; - checkPlayerNames.Location = new Point(3, 54); + checkPlayerNames.Location = new Point(3, 55); checkPlayerNames.Name = "checkPlayerNames"; checkPlayerNames.Padding = new Padding(3, 0, 3, 0); checkPlayerNames.Size = new Size(262, 18); @@ -132,7 +146,7 @@ private void InitializeComponent() // checkAutoCopy // checkAutoCopy.Dock = DockStyle.Top; - checkAutoCopy.Location = new Point(3, 36); + checkAutoCopy.Location = new Point(3, 37); checkAutoCopy.Name = "checkAutoCopy"; checkAutoCopy.Padding = new Padding(3, 0, 3, 0); checkAutoCopy.Size = new Size(262, 18); @@ -144,7 +158,7 @@ private void InitializeComponent() // checkSkipParsedLogs // checkSkipParsedLogs.Dock = DockStyle.Top; - checkSkipParsedLogs.Location = new Point(3, 18); + checkSkipParsedLogs.Location = new Point(3, 19); checkSkipParsedLogs.Name = "checkSkipParsedLogs"; checkSkipParsedLogs.Padding = new Padding(3, 0, 3, 0); checkSkipParsedLogs.Size = new Size(262, 18); @@ -161,9 +175,9 @@ private void InitializeComponent() groupBoxNotifications.Controls.Add(checkXSOverlay); groupBoxNotifications.Dock = DockStyle.Top; groupBoxNotifications.ForeColor = Color.White; - groupBoxNotifications.Location = new Point(8, 137); + groupBoxNotifications.Location = new Point(8, 156); groupBoxNotifications.Name = "groupBoxNotifications"; - groupBoxNotifications.Size = new Size(268, 57); + groupBoxNotifications.Size = new Size(268, 58); groupBoxNotifications.TabIndex = 2; groupBoxNotifications.TabStop = false; groupBoxNotifications.Text = "Notifications"; @@ -172,7 +186,7 @@ private void InitializeComponent() // checkPlayAudio.AutoCheck = false; checkPlayAudio.Dock = DockStyle.Top; - checkPlayAudio.Location = new Point(3, 36); + checkPlayAudio.Location = new Point(3, 37); checkPlayAudio.Name = "checkPlayAudio"; checkPlayAudio.Padding = new Padding(3, 0, 3, 0); checkPlayAudio.Size = new Size(262, 18); @@ -186,7 +200,7 @@ private void InitializeComponent() // checkXSOverlay // checkXSOverlay.Dock = DockStyle.Top; - checkXSOverlay.Location = new Point(3, 18); + checkXSOverlay.Location = new Point(3, 19); checkXSOverlay.Name = "checkXSOverlay"; checkXSOverlay.Padding = new Padding(3, 0, 3, 0); checkXSOverlay.Size = new Size(262, 18); @@ -205,9 +219,9 @@ private void InitializeComponent() groupBox1.Controls.Add(check24Hour); groupBox1.Dock = DockStyle.Top; groupBox1.ForeColor = Color.White; - groupBox1.Location = new Point(8, 194); + groupBox1.Location = new Point(8, 214); groupBox1.Name = "groupBox1"; - groupBox1.Size = new Size(268, 93); + groupBox1.Size = new Size(268, 94); groupBox1.TabIndex = 3; groupBox1.TabStop = false; groupBox1.Text = "Time Formatting"; @@ -215,7 +229,7 @@ private void InitializeComponent() // checkShowDate // checkShowDate.Dock = DockStyle.Top; - checkShowDate.Location = new Point(3, 72); + checkShowDate.Location = new Point(3, 73); checkShowDate.Name = "checkShowDate"; checkShowDate.Padding = new Padding(3, 0, 3, 0); checkShowDate.Size = new Size(262, 18); @@ -227,7 +241,7 @@ private void InitializeComponent() // checkInvertMD // checkInvertMD.Dock = DockStyle.Top; - checkInvertMD.Location = new Point(3, 54); + checkInvertMD.Location = new Point(3, 55); checkInvertMD.Name = "checkInvertMD"; checkInvertMD.Padding = new Padding(3, 0, 3, 0); checkInvertMD.Size = new Size(262, 18); @@ -239,7 +253,7 @@ private void InitializeComponent() // checkShowSeconds // checkShowSeconds.Dock = DockStyle.Top; - checkShowSeconds.Location = new Point(3, 36); + checkShowSeconds.Location = new Point(3, 37); checkShowSeconds.Name = "checkShowSeconds"; checkShowSeconds.Padding = new Padding(3, 0, 3, 0); checkShowSeconds.Size = new Size(262, 18); @@ -251,7 +265,7 @@ private void InitializeComponent() // check24Hour // check24Hour.Dock = DockStyle.Top; - check24Hour.Location = new Point(3, 18); + check24Hour.Location = new Point(3, 19); check24Hour.Name = "check24Hour"; check24Hour.Padding = new Padding(3, 0, 3, 0); check24Hour.Size = new Size(262, 18); @@ -266,7 +280,7 @@ private void InitializeComponent() btnCheckForUpdates.FlatAppearance.BorderColor = Color.FromArgb(122, 122, 122); btnCheckForUpdates.FlatStyle = FlatStyle.Flat; btnCheckForUpdates.ForeColor = Color.White; - btnCheckForUpdates.Location = new Point(8, 332); + btnCheckForUpdates.Location = new Point(8, 356); btnCheckForUpdates.Name = "btnCheckForUpdates"; btnCheckForUpdates.Size = new Size(209, 24); btnCheckForUpdates.TabIndex = 4; @@ -281,7 +295,7 @@ private void InitializeComponent() btnOpenData.FlatAppearance.BorderColor = Color.FromArgb(122, 122, 122); btnOpenData.FlatStyle = FlatStyle.Flat; btnOpenData.ForeColor = Color.White; - btnOpenData.Location = new Point(223, 332); + btnOpenData.Location = new Point(223, 356); btnOpenData.Name = "btnOpenData"; btnOpenData.Size = new Size(53, 24); btnOpenData.TabIndex = 5; @@ -294,26 +308,26 @@ private void InitializeComponent() // ctxData.Items.AddRange(new ToolStripItem[] { setDataLocationToolStripMenuItem }); ctxData.Name = "ctxData"; - ctxData.Size = new Size(215, 48); + ctxData.Size = new Size(193, 26); // // setDataLocationToolStripMenuItem // setDataLocationToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { ctxItemPickFolder, ctxItemResetToDefault }); setDataLocationToolStripMenuItem.Name = "setDataLocationToolStripMenuItem"; - setDataLocationToolStripMenuItem.Size = new Size(214, 22); + setDataLocationToolStripMenuItem.Size = new Size(192, 22); setDataLocationToolStripMenuItem.Text = "Custom Data Location"; // // ctxItemPickFolder // ctxItemPickFolder.Name = "ctxItemPickFolder"; - ctxItemPickFolder.Size = new Size(186, 22); + ctxItemPickFolder.Size = new Size(157, 22); ctxItemPickFolder.Text = "Pick Folder"; ctxItemPickFolder.Click += ctxItemPickFolder_Click; // // ctxItemResetToDefault // ctxItemResetToDefault.Name = "ctxItemResetToDefault"; - ctxItemResetToDefault.Size = new Size(186, 22); + ctxItemResetToDefault.Size = new Size(157, 22); ctxItemResetToDefault.Text = "Reset to Default"; ctxItemResetToDefault.Click += ctxItemResetToDefault_Click; // @@ -330,9 +344,9 @@ private void InitializeComponent() groupBox2.Controls.Add(checkColorObjectives); groupBox2.Dock = DockStyle.Top; groupBox2.ForeColor = Color.White; - groupBox2.Location = new Point(8, 287); + groupBox2.Location = new Point(8, 308); groupBox2.Name = "groupBox2"; - groupBox2.Size = new Size(268, 39); + groupBox2.Size = new Size(268, 40); groupBox2.TabIndex = 6; groupBox2.TabStop = false; groupBox2.Text = "Style"; @@ -340,7 +354,7 @@ private void InitializeComponent() // checkColorObjectives // checkColorObjectives.Dock = DockStyle.Top; - checkColorObjectives.Location = new Point(3, 18); + checkColorObjectives.Location = new Point(3, 19); checkColorObjectives.Name = "checkColorObjectives"; checkColorObjectives.Padding = new Padding(3, 0, 3, 0); checkColorObjectives.Size = new Size(262, 18); @@ -356,7 +370,7 @@ private void InitializeComponent() AutoSize = true; AutoSizeMode = AutoSizeMode.GrowAndShrink; BackColor = Color.FromArgb(46, 52, 64); - ClientSize = new Size(284, 364); + ClientSize = new Size(284, 388); Controls.Add(groupBox2); Controls.Add(btnOpenData); Controls.Add(btnCheckForUpdates); @@ -410,5 +424,6 @@ private void InitializeComponent() private ToolStripMenuItem setDataLocationToolStripMenuItem; private ToolStripMenuItem ctxItemPickFolder; private ToolStripMenuItem ctxItemResetToDefault; + private CheckBox checkDiscordBackup; } } \ No newline at end of file diff --git a/Windows/SettingsWindow.cs b/Windows/SettingsWindow.cs index 233d7bc..27a637e 100644 --- a/Windows/SettingsWindow.cs +++ b/Windows/SettingsWindow.cs @@ -1,6 +1,7 @@ using System.Diagnostics; using ToNSaveManager.Extensions; using ToNSaveManager.Models; +using ToNSaveManager.Utils.Discord; using Timer = System.Windows.Forms.Timer; namespace ToNSaveManager.Windows @@ -62,6 +63,9 @@ private void SettingsWindow_Load(object sender, EventArgs e) checkShowWinLose.CheckedChanged += TimeFormat_CheckedChanged; checkSaveTerrors.CheckedChanged += checkSaveTerrors_CheckedChanged; checkSaveTerrors_CheckedChanged(checkSaveTerrors, e); + + // Discord Backups + checkDiscordBackup.CheckedChanged += CheckDiscordBackup_CheckedChanged; } private void SettingsWindow_FormClosed(object sender, FormClosedEventArgs e) @@ -87,6 +91,36 @@ private void checkSaveTerrors_CheckedChanged(object? sender, EventArgs e) TimeFormat_CheckedChanged(sender, e); } + private void CheckDiscordBackup_CheckedChanged(object? sender, EventArgs e) + { + if (checkDiscordBackup.Checked) + { + string url = Settings.Get.DiscordWebhookURL ?? string.Empty; + EditResult edit = EditWindow.Show(Settings.Get.DiscordWebhookURL ?? string.Empty, "Discord Webhook URL", this); + if (edit.Accept && !edit.Text.Equals(url, StringComparison.Ordinal)) + { + url = edit.Text.Trim(); + + if (!string.IsNullOrWhiteSpace(url)) { + bool valid = DSWebHook.ValidateURL(url); + + if (valid) { + Settings.Get.DiscordWebhookURL = url; + Settings.Export(); + } else { + MessageBox.Show($"The URL your provided does not match a discord webhook url.\n\nMake sure you created your webhook and copied the url correctly.", "Invalid Webhook URL", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } else { + Settings.Get.DiscordWebhookURL = null; + } + } + + if (string.IsNullOrEmpty(Settings.Get.DiscordWebhookURL)) checkDiscordBackup.Checked = false; + } + + MainWindow.Instance?.SetBackupButton(checkDiscordBackup.Checked); + } + private void btnCheckForUpdates_Click(object sender, EventArgs e) { if (Program.StartCheckForUpdate(true)) this.Close(); diff --git a/Windows/SettingsWindow.resx b/Windows/SettingsWindow.resx index 4f83590..693fb3e 100644 --- a/Windows/SettingsWindow.resx +++ b/Windows/SettingsWindow.resx @@ -18,7 +18,7 @@ System.Resources.ResXResourceReader, System.Windows.Forms, ... System.Resources.ResXResourceWriter, System.Windows.Forms, ... this is my long stringthis is a comment - Blue + Blue [base64 mime encoded serialized .NET Framework object] diff --git a/Windows/UpdateWindow.cs b/Windows/UpdateWindow.cs index a4a86fe..17156dd 100644 --- a/Windows/UpdateWindow.cs +++ b/Windows/UpdateWindow.cs @@ -41,6 +41,22 @@ public static void RunPostUpdateCheck(string[] args) try { + using (Process currentProcess = Process.GetCurrentProcess()) + { + Process[] processes = Process.GetProcessesByName(currentProcess.ProcessName); + foreach (Process process in processes) + { + using (process) + { + if (process.Id != currentProcess.Id) + { + process.Kill(); + process.WaitForExit(); + } + } + } + } + if (Directory.Exists(temp)) Directory.Delete(temp, true); } @@ -57,6 +73,7 @@ private void BackgroundWr_DoWork(object? sender, DoWorkEventArgs e) try { + if (File.Exists(TempFileLocation)) File.Delete(TempFileLocation);