private void ExecuteNewArg(User user)
        {
            //Generate the exercise
            Parser.InputSequence newSequence = GenerateExercise(InputGlobals.CurrentConsole);

            //Give greater credit rewards for longer input sequences
            long creditReward = newSequence.Inputs.Count * BaseCreditReward;

            InputExercise inputExercise = new InputExercise(newSequence, creditReward);

            UserExercises[user.Name] = inputExercise;

            OutputInputExercise(inputExercise);
        }
Exemple #2
0
        public override void ExecuteCommand(EvtChatCommandArgs e)
        {
            string args = e.Command.ArgumentsAsString;

            if (string.IsNullOrEmpty(args) == true)
            {
                BotProgram.MsgHandler.QueueMessage("Usage: \"Input\"");
                return;
            }

            //Parse the input
            //Parser.InputSequence inputSequence = default;
            //(bool, List<List<Parser.Input>>, bool, int) parsedVal = default;
            Parser.InputSequence inputSequence = default;

            try
            {
                string parse_message = Parser.Expandify(Parser.PopulateMacros(args));

                inputSequence = Parser.ParseInputs(parse_message, 0, true, true);
                //parsedVal = Parser.Parse(parse_message);
            }
            catch
            {
                inputSequence.InputValidationType = Parser.InputValidationTypes.Invalid;
                //parsedVal.Item1 = false;
            }

            if (inputSequence.InputValidationType != Parser.InputValidationTypes.Valid)
            {
                BotProgram.MsgHandler.QueueMessage("Invalid input. Note that length cannot be determined for dynamic macros without inputs filled in.");
                return;
            }

            BotProgram.MsgHandler.QueueMessage($"Total length: {inputSequence.TotalDuration}ms");
        }
Exemple #3
0
        //NOTE: This would result in lots of code duplication if other streaming services were integrated
        //Is there a better way to do this?

        private void ProcessMsgAsInput(User userData, EvtUserMessageArgs e)
        {
            //Don't process for inputs if a meme
            string possibleMeme = e.UsrMessage.Message.ToLower();

            if (BotProgram.BotData.Memes.TryGetValue(possibleMeme, out string meme) == true)
            {
                return;
            }

            //Ignore commands as inputs
            if (possibleMeme.StartsWith(Globals.CommandIdentifier) == true)
            {
                return;
            }

            //If there are no valid inputs, don't attempt to parse
            if (InputGlobals.CurrentConsole.ValidInputs == null || InputGlobals.CurrentConsole.ValidInputs.Length == 0)
            {
                return;
            }

            //Parser.InputSequence inputSequence = default;
            //(bool, List<List<Parser.Input>>, bool, int) parsedVal = default;
            Parser.InputSequence inputSequence = default;

            try
            {
                string parse_message = Parser.Expandify(Parser.PopulateMacros(e.UsrMessage.Message));
                inputSequence = Parser.ParseInputs(parse_message, userData.Team, true, true);
                //parsedVal = Parser.Parse(parse_message);
                //Console.WriteLine(inputSequence.ToString());
                //Console.WriteLine("\nReverse Parsed: " + ReverseParser.ReverseParse(inputSequence));
                //Console.WriteLine("\nReverse Parsed Natural:\n" + ReverseParser.ReverseParseNatural(inputSequence));
            }
            catch (Exception exception)
            {
                string excMsg = exception.Message;

                //Kimimaru: Sanitize parsing exceptions
                //Most of these are currently caused by differences in how C# and Python handle slicing strings (Substring() vs string[:])
                //One example that throws this that shouldn't is "#mash(w234"
                //BotProgram.MsgHandler.QueueMessage($"ERROR: {excMsg}");
                inputSequence.InputValidationType = Parser.InputValidationTypes.Invalid;
                //parsedVal.Item1 = false;
            }

            //Check for non-valid messages
            if (inputSequence.InputValidationType != Parser.InputValidationTypes.Valid)
            {
                //Display error message for invalid inputs
                if (inputSequence.InputValidationType == Parser.InputValidationTypes.Invalid)
                {
                    BotProgram.MsgHandler.QueueMessage(inputSequence.Error);
                }

                return;
            }

            //It's a valid message, so process it

            //Ignore if user is silenced
            if (userData.Silenced == true)
            {
                return;
            }

            //Ignore based on user level and permissions
            if (userData.Level < BotProgram.BotData.InputPermissions)
            {
                BotProgram.MsgHandler.QueueMessage($"Inputs are restricted to levels {(AccessLevels.Levels)BotProgram.BotData.InputPermissions} and above");
                return;
            }

            #region Parser Post-Process Validation

            /* All this validation is very slow
             * Find a way to speed it up, ideally without integrating it directly into the parser
             */

            //Check if the user has permission to perform all the inputs they attempted
            //Also validate that the controller ports they're inputting for are valid
            ParserPostProcess.InputValidation inputValidation = ParserPostProcess.CheckInputPermissionsAndPorts(userData.Level, inputSequence.Inputs,
                                                                                                                BotProgram.BotData.InputAccess.InputAccessDict);

            //If the input isn't valid, exit
            if (inputValidation.IsValid == false)
            {
                if (string.IsNullOrEmpty(inputValidation.Message) == false)
                {
                    BotProgram.MsgHandler.QueueMessage(inputValidation.Message);
                }
                return;
            }

            //Lastly, check for invalid button combos given the current console
            if (BotProgram.BotData.InvalidBtnCombos.InvalidCombos.TryGetValue((int)InputGlobals.CurrentConsoleVal, out List <string> invalidCombos) == true)
            {
                bool buttonCombosValidated = ParserPostProcess.ValidateButtonCombos(inputSequence.Inputs, invalidCombos);

                if (buttonCombosValidated == false)
                {
                    string msg    = "Invalid input: buttons ({0}) are not allowed to be pressed at the same time.";
                    string combos = string.Empty;

                    for (int i = 0; i < invalidCombos.Count; i++)
                    {
                        combos += "\"" + invalidCombos[i] + "\"";

                        if (i < (invalidCombos.Count - 1))
                        {
                            combos += ", ";
                        }
                    }

                    msg = string.Format(msg, combos);
                    BotProgram.MsgHandler.QueueMessage(msg);

                    return;
                }
            }

            #endregion

            if (InputHandler.StopRunningInputs == false)
            {
                //Invoke input event
                UserMadeInputEvent?.Invoke(userData, e, inputSequence);
            }
            else
            {
                BotProgram.MsgHandler.QueueMessage("New inputs cannot be processed until all other inputs have stopped.");
            }
        }
        public override void ExecuteCommand(EvtChatCommandArgs e)
        {
            List <string> args = e.Command.ArgumentsAsList;

            if (args.Count < 2)
            {
                BotProgram.MsgHandler.QueueMessage($"{Globals.CommandIdentifier}addmacro usage: \"#macroname\" \"command\"");
                return;
            }

            //Make sure the first argument has at least two characters
            if (args[0].Length < 2)
            {
                BotProgram.MsgHandler.QueueMessage("Macros need to be at least two characters!");
                return;
            }

            string macroName = args[0].ToLowerInvariant();

            if (macroName[0] != Globals.MacroIdentifier)
            {
                BotProgram.MsgHandler.QueueMessage($"Macros must start with '{Globals.MacroIdentifier}'.");
                return;
            }

            //For simplicity with wait inputs, force the first character in the macro name to be alphanumeric
            if (char.IsLetterOrDigit(args[0][1]) == false)
            {
                BotProgram.MsgHandler.QueueMessage("The first character in macro names must be alphanumeric!");
                return;
            }

            if (macroName.Length > MAX_MACRO_LENGTH)
            {
                BotProgram.MsgHandler.QueueMessage($"The max macro length is {MAX_MACRO_LENGTH} characters!");
                return;
            }

            string macroVal = e.Command.ArgumentsAsString.Remove(0, macroName.Length + 1).ToLowerInvariant();

            bool   isDynamic = false;
            string parsedVal = macroVal;

            //Check for a dynamic macro
            if (macroName.Contains("(*") == true)
            {
                isDynamic = true;

                //Dynamic macros can't be fully verified until we do some brute forcing
                //An example is: "a500ms [b .]*<0>"
                //The <0> should be a number, so if we use a valid input it won't work
                //The brute force approach would check with all possible combinations of the first input (Ex. "a") and a number
                //If any are valid, it's a valid dynamic macro

                //NOTE: We need to verify that the dynamic macro takes the form of "#macroname(*,*)"
                //It needs to have an open parenthesis followed by a number of asterisks separated by commas, then ending with a closed parenthesis
                //string parseMsg = string.Empty;
                //try
                //{
                //    parseMsg = Parser.Expandify(Parser.PopulateMacros(parsedVal));
                //}
                //catch (Exception exception)
                //{
                //    BotProgram.MsgHandler.QueueMessage("Invalid dynamic macro. Ensure that variables are listed in order (Ex. (*,*,...) = <0>, <1>,...)");
                //    Console.WriteLine(exception.Message);
                //    return;
                //}
                //
                //MatchCollection matches = Regex.Matches(parseMsg, @"<[0-9]+>", RegexOptions.Compiled);
                //
                ////Kimimaru: Replace all variables with a valid input to verify its validity
                ////Any input will do, so just grab the first one
                //string input = InputGlobals.ValidInputs[0];
                //
                //for (int i = 0; i < matches.Count; i++)
                //{
                //    Match match = matches[i];
                //
                //    parsedVal = parsedVal.Replace(match.Value, input);
                //}
            }

            //Validate input if not dynamic
            if (isDynamic == false)
            {
                try
                {
                    string parse_message = Parser.Expandify(Parser.PopulateMacros(parsedVal));

                    Parser.InputSequence inputSequence = Parser.ParseInputs(parse_message, 0, true, true);
                    //var val = Parser.Parse(parse_message);

                    if (inputSequence.InputValidationType != Parser.InputValidationTypes.Valid)//val.Item1 == false)
                    {
                        BotProgram.MsgHandler.QueueMessage("Invalid macro.");
                        return;
                    }
                }
                catch
                {
                    BotProgram.MsgHandler.QueueMessage("Invalid macro.");
                    return;
                }
            }

            //Parser.InputSequence inputSequence = default;
            //
            //try
            //{
            //    //Parse the macro to check for valid input
            //    string parse_message = Parser.Expandify(Parser.PopulateMacros(parsedVal));
            //
            //    inputSequence = Parser.ParseInputs(parse_message);
            //}
            //catch
            //{
            //    if (isDynamic == false)
            //    {
            //        BotProgram.MsgHandler.QueueMessage("Invalid macro.");
            //    }
            //    else
            //    {
            //        BotProgram.MsgHandler.QueueMessage("Invalid dynamic macro. Ensure that variables are listed in order (Ex. (*,*,...) = <0>, <1>,...)");
            //    }
            //    return;
            //}

            //if (inputSequence.InputValidationType != Parser.InputValidationTypes.Valid)
            //{
            //    if (isDynamic == false)
            //    {
            //        BotProgram.MsgHandler.QueueMessage("Invalid macro.");
            //    }
            //    else
            //    {
            //        BotProgram.MsgHandler.QueueMessage("Invalid dynamic macro. Ensure that variables are listed in order (Ex. (*,*,...) = <0>, <1>,...)");
            //    }
            //}
            //else
            //{
            string message = string.Empty;

            if (BotProgram.BotData.Macros.ContainsKey(macroName) == false)
            {
                if (isDynamic == false)
                {
                    message = $"Added macro {macroName}!";
                }
                else
                {
                    message = $"Added dynamic macro {macroName}! Dynamic macros can't be validated beforehand, so verify it works manually.";
                }

                AddMacroToParserList(macroName);
            }
            else
            {
                if (isDynamic == false)
                {
                    message = $"Updated macro {macroName}!";
                }
                else
                {
                    message = $"Updated dynamic macro {macroName}! Dynamic macros can't be validated beforehand, so verify it works manually.";
                }
            }

            BotProgram.BotData.Macros[macroName] = macroVal;
            BotProgram.SaveBotData();

            BotProgram.MsgHandler.QueueMessage(message);
            //}
        }