From 75cd908f436fea843ffbebf83e2e547524990902 Mon Sep 17 00:00:00 2001 From: Sanel Kukic Date: Tue, 30 Jun 2020 10:33:16 -0400 Subject: [PATCH] fix #1 and #2 --- src/.idea/.idea.sphk/.idea/.name | 1 + src/.idea/.idea.sphk/.idea/vcs.xml | 6 + src/sphk/Program.cs | 53 ++++++- src/sphk/Properties/AssemblyInfo.cs | 4 +- src/sphk_gui/Form1.cs | 24 ++- src/sphk_gui/Properties/AssemblyInfo.cs | 4 +- src/sphk_gui/SpamForm.cs | 199 ++++++++++++++++++++++-- 7 files changed, 255 insertions(+), 36 deletions(-) create mode 100644 src/.idea/.idea.sphk/.idea/.name create mode 100644 src/.idea/.idea.sphk/.idea/vcs.xml diff --git a/src/.idea/.idea.sphk/.idea/.name b/src/.idea/.idea.sphk/.idea/.name new file mode 100644 index 0000000..cdcbfc9 --- /dev/null +++ b/src/.idea/.idea.sphk/.idea/.name @@ -0,0 +1 @@ +sphk \ No newline at end of file diff --git a/src/.idea/.idea.sphk/.idea/vcs.xml b/src/.idea/.idea.sphk/.idea/vcs.xml new file mode 100644 index 0000000..2e3f692 --- /dev/null +++ b/src/.idea/.idea.sphk/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/sphk/Program.cs b/src/sphk/Program.cs index 931d278..890bffb 100644 --- a/src/sphk/Program.cs +++ b/src/sphk/Program.cs @@ -21,6 +21,7 @@ using System.IO; using System.Linq; using System.Net; +using System.Reflection; using System.Threading; namespace sphk @@ -34,10 +35,17 @@ internal class Program // The program's entrypoint public static void Main(string[] args) { + // welcome and version information + Version _version = Assembly.GetExecutingAssembly().GetName().Version; + string __version = $@"{_version.Major}.{_version.Minor}.{_version.Build}.{_version.Revision}"; + Console.WriteLine("sphk"); + Console.WriteLine($"CLI version {__version}"); + Console.WriteLine("Copyright 2020 3reetop"); + Console.WriteLine("Licensed under the terms of the MIT License"); + Console.WriteLine("-----------------------"); // If we did not specify any commandline arguments, show a basic help message and exit with code 1 if (args.Length == 0) { - Console.WriteLine("SpamHook version 4, by 3reetop\n"); Console.WriteLine("Please specify the location of your .json configuration file!\n"); Console.WriteLine("If you want to generate a file, run this program with the 'generate' command."); Console.WriteLine( @@ -226,6 +234,7 @@ public static void Spam() timeout_length = timeout_length * 1000; // If the user wants to spam this webhook forever (which is what -1 means) + string output = ""; if (times_to_spam == -1) { // Create an integer holding the number of the request we're currently on @@ -241,20 +250,35 @@ public static void Spam() if (status == 0) { // Print a success message to standard output - Console.WriteLine($@"Successfully sent request {request_number}"); + output = $@"Successfully sent request {request_number}"; + if (_debug) + { + output += " (204 No Content response)"; + } + Console.WriteLine(output); } // Otherwise, if the value of the status integer is 1, meaning we reached Discord's // ratelimit else if (status == 1) { + output = $@"We've hit the ratelimit on request number {request_number}"; + if (_debug) + { + output += " (429 Too Many Requests response)"; + } // Print a ratelimit warning to standard output - Console.WriteLine($@"We've hit the ratelimit on request number {request_number}"); + Console.WriteLine(output); } // Otherwise, if the value of the status integer is 2, meaning the request failed else if (status == 2) { + output = $@"An error was encountered when trying to send request {request_number}"; + if (_debug) + { + output += " (400 Bad Request response)"; + } // Print a failure message to standard output - Console.WriteLine($@"An error was encountered when trying to send request {request_number}"); + Console.WriteLine(output); } // Usually, you shouldn't be able to reach this block of code below // But if you somehow do, might as well put a nice little easter egg in there, eh? @@ -287,23 +311,38 @@ public static void Spam() // was successful if (status == 0) { + output = $@"Successfully sent request {i} out of {times_to_spam}"; + if (_debug) + { + output += " (204 No Content response)"; + } // Then print a success message to standard output - Console.WriteLine($@"Successfully sent request {i} out of {times_to_spam}"); + Console.WriteLine(output); } // Otherwise, if the return code from SendRequest() was 1, meaning // that we hit Discord's rate limit else if (status == 1) { + output = $@"We've hit the ratelimit on request number {i} out of {times_to_spam}"; + if (_debug) + { + output += " (429 Too Many Requests response)"; + } // Then print a ratelimit warning to standard output - Console.WriteLine($@"We've hit the ratelimit on request number {i} out of {times_to_spam}"); + Console.WriteLine(output); } // Otherwise, if the return code from SendRequest() was 2, meaning the // request was a failure else if (status == 2) { + output = $@"An error was encountered when trying to send request {i} out of {times_to_spam}"; + if (_debug) + { + output += " (400 Bad Request response)"; + } // Then print a failure message to standard output Console.WriteLine( - $@"An error was encountered when trying to send request {i} out of {times_to_spam}"); + output); } // Usually, you shouldn't be able to reach this block of code below // But, if you somehow do, might as well put a nice little easter egg in there, eh? diff --git a/src/sphk/Properties/AssemblyInfo.cs b/src/sphk/Properties/AssemblyInfo.cs index 4355a07..a733f52 100644 --- a/src/sphk/Properties/AssemblyInfo.cs +++ b/src/sphk/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file +[assembly: AssemblyVersion("1.0.0.1")] +[assembly: AssemblyFileVersion("1.0.0.1")] \ No newline at end of file diff --git a/src/sphk_gui/Form1.cs b/src/sphk_gui/Form1.cs index 9e33928..cca5d5f 100644 --- a/src/sphk_gui/Form1.cs +++ b/src/sphk_gui/Form1.cs @@ -27,7 +27,8 @@ namespace sphk_gui public partial class Form1 : Form { // Create a publicly accessible boolean that determines if we're in debug mode - public bool is_debug; + public static bool is_debug = false; + private SpamForm _form = new SpamForm(is_debug); public Form1() { InitializeComponent(); @@ -148,15 +149,8 @@ private void generateConfigFileButton_Click(object sender, EventArgs e) else { // If the user cancels the SaveFileDialog by clicking the Cancel button, show a warning - DialogResult res = MessageBox.Show("An error was encountered when trying to open the dialog.", + MessageBox.Show("Please select a file to save the config to!", "Oops", MessageBoxButtons.OK, MessageBoxIcon.Question); - switch (res) - { - // And then once the user acknowledges the warning, close the Form - default: - Close(); - break; - } } } @@ -165,14 +159,18 @@ private void generateConfigFileButton_Click(object sender, EventArgs e) private void debugModeCheck_CheckedChanged(object sender, EventArgs e) { // If the debug mode checkbox is checked, set the is_debug boolean to true + // and set the is_debug property in our SpamForm instance to false if (debugModeCheck.Checked) { is_debug = true; + _form.is_debug = true; } // If the debug mode checkbox is not checked, set the is_debug boolean to false + // and set the is_debug property in our SpamForm instance to false else { is_debug = false; + _form.is_debug = false; } } @@ -180,11 +178,9 @@ private void debugModeCheck_CheckedChanged(object sender, EventArgs e) // in the GUI private void startSpamButton_Click_1(object sender, EventArgs e) { - // Create a new instance of the SpamForm and display it - // The SpamForm handles everything from here in it's Load event handler - // so this is all we need to do here. - SpamForm form = new SpamForm(); - form.ShowDialog(); + // Use the instance of SpamForm we created at the very beginning + // and call it's ShowDialog method + _form.ShowDialog(); } } } \ No newline at end of file diff --git a/src/sphk_gui/Properties/AssemblyInfo.cs b/src/sphk_gui/Properties/AssemblyInfo.cs index 3082c29..7722caa 100644 --- a/src/sphk_gui/Properties/AssemblyInfo.cs +++ b/src/sphk_gui/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file +[assembly: AssemblyVersion("1.0.0.1")] +[assembly: AssemblyFileVersion("1.0.0.1")] \ No newline at end of file diff --git a/src/sphk_gui/SpamForm.cs b/src/sphk_gui/SpamForm.cs index 5c6e8e6..8aacad6 100644 --- a/src/sphk_gui/SpamForm.cs +++ b/src/sphk_gui/SpamForm.cs @@ -17,6 +17,7 @@ // OTHER DEALINGS IN THE SOFTWARE. using System; +using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Reflection; @@ -27,18 +28,34 @@ namespace sphk_gui { public partial class SpamForm : Form { - // Get the debug boolean directly from Form1 - private bool is_debug = new Form1().is_debug; + // boolean to store debug mode flag, defaults to false + public bool is_debug = false; + // Define cli_process as a new Process object we'll use later private Process cli_process; - public SpamForm() + public SpamForm(bool _is_debug) { InitializeComponent(); + // if a debug mode flag set to true is passed in the constructor, then set the + // debug mode boolean is_debug in this form to true + // + // the way i managed to get Form1 and SpamForm to communicate with each other is to + // have an event handler in Form1, and to create a new instance of SpamForm in the scope of + // the entire Form1 class, and then updating the is_debug property of the SpamForm instance + // anytime the event handler fires + // + // sounds hacky but it works + if (is_debug) + { + is_debug = _is_debug; + } } private void SpamForm_Load(object sender, EventArgs e) { + // clear all text from the commandLineOutputBox control + commandlineOutputBox.Clear(); // As soon as the form is loaded, open the OpenFileDialog if (openConfigDialog.ShowDialog() == DialogResult.OK) { @@ -92,7 +109,7 @@ private void SpamForm_Load(object sender, EventArgs e) else { // This warning will show if the user cancels the OpenFileDialog by clicking the Cancel button - DialogResult res = MessageBox.Show("An error was encountered while trying to open the dialog", + DialogResult res = MessageBox.Show("Please select a file!", "Oops", MessageBoxButtons.OK, MessageBoxIcon.Question); switch (res) { @@ -158,16 +175,176 @@ private void closeWindowButton_Click(object sender, EventArgs e) // We likely don't need the StringBuilder at all and we might be able to just // call AppendText on the RichTextBox control directly, but I guess it's better to // be safe than sorry - StringBuilder builder = new StringBuilder(); - builder.Append("\nExiting..."); - commandlineOutputBox.AppendText(builder.ToString()); - cli_process.Kill(); - this.Close(); + try + { + StringBuilder builder = new StringBuilder(); + builder.Append("\nExiting..."); + commandlineOutputBox.AppendText(builder.ToString()); + // if the sphk.exe process is not null (to avoid NullReferenceExceptions) + if (cli_process != null) + { + // AND the process has not already exited on its own + if (!cli_process.HasExited) + { + // forcefully kill it + cli_process.Kill(); + } + + // and then close the currently open window + Close(); + } + } + catch (InvalidOperationException ex) + { + // this exception is thrown when the process has already exited, which fixes + // issue #1 + // we should just ignore the exception and close the form, since sphk.exe has + // already been killed or has exited on its own + // + // but if we're in debug mode, show an exception stack trace to the user + if (is_debug) + { + MessageBox.Show(ex.ToString(), "Error killing sphk.exe process", MessageBoxButtons.OK, + MessageBoxIcon.Error); + } + + // and then close the form/window + Close(); + } + catch (Win32Exception ex) + { + // this exception handler will take care of any situation where + // the process could not be terminated for whatever reason + // + // in this situation, we'll show a nice and user-friendly error message + // (optionally with the exception stack trace appended to it if debug mode is on) + // and exit the program forcefully + // + if (is_debug) + { + // show an error to the user containing the exception stacktrace + MessageBox.Show(ex.ToString(), "Error killing sphk.exe process", MessageBoxButtons.OK, + MessageBoxIcon.Error); + } + + // otherwise just close the current window gracefully + Close(); + } + catch (Exception ex) + { + // this exception handler will take care of any other exception that the above 2 handlers + // cannot + // + // it really just does the exact same thing as the ones above. + // + // a string to store our error message in + string error_msg = "Failed to terminate sphk.exe process."; + if (is_debug) + { + // append the exception stacktrace to the error message if we're in debug mode + error_msg += "\n" + ex.ToString(); + } + + // show the message box to the user + DialogResult res = MessageBox.Show(error_msg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + switch (res) + { + // once the user acknowledges the message box, forcefully exit the entire application + default: + Environment.Exit(1); + break; + } + } } - private void SpamForm_FormClosing(object sender, EventArgs e) + private void SpamForm_FormClosing(object sender, FormClosingEventArgs e) { - cli_process.Kill(); + // clear the contents of the output log textbox + commandlineOutputBox.Clear(); + try + { + // if the sphk.exe process is not null + if (cli_process != null) + { + // and if it hasn't already exited on its own + if (!cli_process.HasExited) + { + // then kill it + cli_process.Kill(); + } + } + } + catch (InvalidOperationException ex) + { + // this exception handler fixes issue #1 + // + // if we're in debug mode + if (is_debug) + { + // show an error to the user containing the exception stacktrace + MessageBox.Show(ex.ToString(), "Error killing sphk.exe process", MessageBoxButtons.OK, + MessageBoxIcon.Error); + } + + // otherwise just close the current window gracefully + Close(); + } + catch (Win32Exception ex) + { + // if we're in debug mode + if (is_debug) + { + // show an error to the user containing the exception stacktrace + MessageBox.Show(ex.ToString(), "Error killing sphk.exe process", MessageBoxButtons.OK, + MessageBoxIcon.Error); + } + + // otherwise just close the current window gracefully + Close(); + } + catch (NullReferenceException ex) + { + // fixes an issue where cancelling the OpenFileDialog results in a + // NullReferenceException when the form closes + // + // this exception was being thrown because I was not checking if cli_process was null + // and when you don't select a config file, it is null + // + // and trying to access the HasExited property or trying to call .Kill on a null object + // obviously throws a NullReferenceException + if (is_debug) + { + MessageBox.Show(ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + + // close the form window + Close(); + } + catch (Exception ex) + { + // this exception handler will take care of any other exception that the above 2 handlers + // cannot + // + // it really just does the exact same thing as the ones above. + // + // a string to store our error message in + string error_msg = "Failed to terminate sphk.exe process."; + if (is_debug) + { + // append the exception stacktrace to the error message if we're in debug mode + error_msg += "\n" + ex.ToString(); + } + + // show the message box to the user + DialogResult res = MessageBox.Show(error_msg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + switch (res) + { + // once the user acknowledges the message box, forcefully exit the entire application + default: + Environment.Exit(1); + break; + } + } } } } \ No newline at end of file