Example #1
0
        /// <inheritdoc />
        public override async Task Process(LSGlobals ls)
        {
            var data = ls.BotData;
            await base.Process(ls);

            var browser = data.TryGetObject <WebDriver>("selenium");

            if (browser == null)
            {
                throw new Exception("Open a browser first!");
            }

            data.Logger.Log("Executing JS code!", LogColors.White);

            var returned = browser.ExecuteScript(ReplaceValues(JavascriptCode, ls));

            if (returned != null)
            {
                try
                {
                    InsertVariable(ls, IsCapture, false, new List <string>()
                    {
                        returned.ToString()
                    }, OutputVariable, "", "", false, true);
                }
                catch
                {
                    throw new Exception($"Failed to convert the returned value to a string");
                }
            }

            data.Logger.Log("... executed!", LogColors.White);

            UpdateSeleniumData(data);
        }
Example #2
0
        /// <inheritdoc />
        public override async Task Process(LSGlobals ls)
        {
            var data = ls.BotData;
            await base.Process(ls);

            var provider = data.Providers.Captcha;

            data.Logger.Log("WARNING! This block is obsolete and WILL BE REMOVED IN THE FUTURE! Use the SOLVECAPTCHA block!", LogColors.Tomato);
            data.Logger.Log("Solving reCaptcha...", LogColors.White);

            var recapResponse = "";

            try
            {
                var response = await provider.SolveRecaptchaV2Async(ReplaceValues(SiteKey, ls), ReplaceValues(Url, ls));

                recapResponse = response.Response;
            }
            catch (Exception ex)
            {
                data.Logger.Log(ex.Message, LogColors.Tomato);
                throw;
            }

            data.Logger.Log($"Succesfully got the response: {recapResponse}", LogColors.GreenYellow);

            if (VariableName != string.Empty)
            {
                GetVariables(data).Set(new StringVariable(recapResponse)
                {
                    Name = VariableName
                });
                data.Logger.Log($"Response stored in variable: {VariableName}.", LogColors.White);
            }
        }
Example #3
0
        /// <inheritdoc />
        public override async Task Process(LSGlobals ls)
        {
            var data = ls.BotData;
            await base.Process(ls);

            var provider = data.Providers.Captcha;

            // If bypass balance check, skip this method.
            if (!provider.CheckBalanceBeforeSolving)
            {
                return;
            }

            // Get balance. If balance is under a certain threshold, don't ask for captcha solve
            Balance = 0; // Reset it or the block will save it for future calls
            data.Logger.Log("Checking balance...", LogColors.White);

            Balance = await provider.GetBalanceAsync();

            if (Balance <= 0)
            {
                throw new Exception($"[{provider.ServiceType}] Bad token/credentials or zero balance!");
            }

            data.Logger.Log($"[{provider.ServiceType}] Current Balance: ${Balance}", LogColors.GreenYellow);
            data.CaptchaCredit = Balance;
        }
Example #4
0
        /// <summary>
        /// Gets a command Action from a command line.
        /// </summary>
        internal static Action Parse(string line, LSGlobals ls)
        {
            // Trim the line
            var input = line.Trim();

            // Return an exception if the line is empty
            if (input == string.Empty)
            {
                throw new ArgumentNullException();
            }

            var label = LineParser.ParseToken(ref input, TokenType.Label, false);

            // Parse the identifier
            var identifier = "";

            try
            {
                identifier = LineParser.ParseToken(ref input, TokenType.Parameter, true);
            }
            catch
            {
                throw new ArgumentException("Missing identifier");
            }

            return((CommandName)Enum.Parse(typeof(CommandName), identifier, true) switch
            {
                CommandName.PRINT => new Action(() => ls.BotData.Logger.Log(BlockBase.ReplaceValues(input, ls), LogColors.White)),
                CommandName.SET => SetParser.Parse(input, ls),
                CommandName.DELETE => DeleteParser.Parse(input, ls),
                // TODO: Readd this
                // CommandName.MOUSEACTION => MouseActionParser.Parse(input, ls),
                _ => throw new ArgumentException($"Invalid identifier '{identifier}'"),
            });
Example #5
0
        /// <inheritdoc />
        public override async Task Process(LSGlobals ls)
        {
            var data = ls.BotData;
            await base.Process(ls);

            var browser = data.TryGetObject <WebDriver>("selenium");

            if (browser == null)
            {
                throw new Exception("Open a browser first!");
            }

            var replacedUrl = ReplaceValues(Url, ls);

            data.Logger.Log($"Navigating to {replacedUrl}", LogColors.White);
            browser.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(Timeout);

            try
            {
                browser.Navigate().GoToUrl(replacedUrl);
                data.Logger.Log("Navigated!", LogColors.White);
            }
            catch (WebDriverTimeoutException)
            {
                data.Logger.Log("Timeout on Page Load", LogColors.Tomato);

                if (BanOnTimeout)
                {
                    data.STATUS = "BAN";
                }
            }

            UpdateSeleniumData(data);
        }
Example #6
0
        /// <summary>
        /// Adds a single or list variable with the given value.
        /// </summary>
        protected static void InsertVariable(LSGlobals ls, bool isCapture, bool recursive, IEnumerable <string> values, string variableName,
                                             string prefix = "", string suffix = "", bool urlEncode = false, bool createEmpty = true)
        {
            var data = ls.BotData;
            var list = values.Select(v => ReplaceValues(prefix, ls) + v.Trim() + ReplaceValues(suffix, ls)).ToList();

            if (urlEncode)
            {
                list = list.Select(v => Uri.EscapeDataString(v)).ToList();
            }

            Variable variable = null;

            if (recursive)
            {
                if (list.Count > 0 || createEmpty)
                {
                    variable = new ListOfStringsVariable(list)
                    {
                        Name = variableName
                    };
                }
            }
            else
            {
                if (list.Count == 0)
                {
                    if (createEmpty)
                    {
                        variable = new StringVariable(string.Empty)
                        {
                            Name = variableName
                        };
                    }
                }
                else
                {
                    variable = new StringVariable(list.First())
                    {
                        Name = variableName
                    };
                }
            }

            if (variable != null)
            {
                GetVariables(data).Set(variable);
                data.Logger.Log($"Parsed variable | Name: {variable.Name} | Value: {variable.AsString()}", isCapture ? LogColors.OrangeRed : LogColors.Gold);
                variable.MarkedForCapture = isCapture;
            }
            else
            {
                data.Logger.Log("Could not parse any data. The variable was not created.", LogColors.White);
            }
        }
Example #7
0
        /// <summary>
        /// Parses a condition made of left-hand term, condition type and right-hand term and verifies if it's true.
        /// </summary>
        /// <param name="cfLine">The reference to the line to parse</param>
        /// <param name="data">The BotData needed for variable replacement</param>
        /// <returns></returns>
        public static bool ParseCheckCondition(ref string cfLine, LSGlobals ls)
        {
            var first    = LineParser.ParseLiteral(ref cfLine, "STRING");
            var Comparer = (Comparer)LineParser.ParseEnum(ref cfLine, "Comparer", typeof(Comparer));
            var second   = "";

            if (Comparer != Comparer.Exists && Comparer != Comparer.DoesNotExist)
            {
                second = LineParser.ParseLiteral(ref cfLine, "STRING");
            }

            return(Condition.ReplaceAndVerify(first, Comparer, second, ls));
        }
        /// <inheritdoc />
        public override async Task Process(LSGlobals ls)
        {
            var data = ls.BotData;
            await base.Process(ls);

            string errorMessage;
            var    provider = data.Providers.Captcha;

            try
            {
                try
                {
                    var replacedId = ReplaceValues(CaptchaId, ls);
                    await provider.ReportSolution(long.Parse(replacedId), Type);

                    data.Logger.Log($"Captcha reported successfully!", LogColors.GreenYellow);
                    return;
                }
                catch (Exception ex) // This unwraps aggregate exceptions
                {
                    if (ex is AggregateException)
                    {
                        throw ex.InnerException;
                    }
                    else
                    {
                        throw;
                    }
                }
            }
            catch (TaskReportException ex)
            {
                errorMessage = $"The captcha report was not accepted! {ex.Message}";
            }
            catch (NotSupportedException ex)
            {
                errorMessage = $"The currently selected service ({provider.ServiceType}) does not support reports! {ex.Message}";
            }
            catch (Exception ex)
            {
                errorMessage = $"An error occurred! {ex.Message}";
            }


            if (!string.IsNullOrEmpty(errorMessage))
            {
                data.Logger.Log(errorMessage, LogColors.Tomato);
            }
        }
Example #9
0
        /// <inheritdoc />
        public override async Task Process(LSGlobals ls)
        {
            var data = ls.BotData;
            await base.Process(ls);

            string errorMessage;

            Proxy proxy = data.UseProxy && UseProxy
                ? proxy = new Proxy
            {
                Host      = data.Proxy.Host,
                Port      = data.Proxy.Port,
                Type      = (ProxyType)Enum.Parse(typeof(ProxyType), data.Proxy.Type.ToString()),
                Username  = data.Proxy.Username,
                Password  = data.Proxy.Password,
                UserAgent = UserAgent,
                Cookies   = data.COOKIES.ToList().Concat(ls.GlobalCookies.ToList()).Select(p => (p.Key, p.Value)).ToArray()
            }
Example #10
0
        /// <summary>
        /// Replaces the values and verifies if a condition is true or false.
        /// </summary>
        public static bool ReplaceAndVerify(KeycheckCondition kcCond, LSGlobals ls)
        {
            var style    = NumberStyles.Number | NumberStyles.AllowCurrencySymbol; // Needed when comparing values with a currency symbol
            var provider = new CultureInfo("en-US");
            var L        = BlockBase.ReplaceValuesRecursive(kcCond.Left, ls);      // The left-hand term can accept recursive values like <LIST[*]>
            var r        = BlockBase.ReplaceValues(kcCond.Right, ls);              // The right-hand term cannot

            switch (kcCond.Comparer)
            {
            case Comparer.EqualTo:
                return(L.Any(l => l == r));

            case Comparer.NotEqualTo:
                return(L.Any(l => l != r));

            case Comparer.GreaterThan:
                return(L.Any(l => decimal.Parse(l.Replace(',', '.'), style, provider) > decimal.Parse(r.Replace(',', '.'), style, provider)));

            case Comparer.LessThan:
                return(L.Any(l => decimal.Parse(l.Replace(',', '.'), style, provider) < decimal.Parse(r.Replace(',', '.'), style, provider)));

            case Comparer.Contains:
                return(L.Any(l => l.Contains(r)));

            case Comparer.DoesNotContain:
                return(L.Any(l => !l.Contains(r)));

            case Comparer.Exists:
                return(L.Any(l => l != kcCond.Left));    // Returns true if any replacement took place

            case Comparer.DoesNotExist:
                return(L.All(l => l == kcCond.Left));    // Returns true if no replacement took place

            case Comparer.MatchesRegex:
                return(L.Any(l => Regex.Match(l, r).Success));

            case Comparer.DoesNotMatchRegex:
                return(L.Any(l => !Regex.Match(l, r).Success));

            default:
                return(false);
            }
        }
Example #11
0
        /// <inheritdoc />
        public override async Task Process(LSGlobals ls)
        {
            var data = ls.BotData;
            await base.Process(ls);

            var original = ReplaceValues(ParseTarget, ls);
            var list     = Type switch
            {
                ParseType.LR => ParseLR(original, ReplaceValues(LeftString, ls), ReplaceValues(RightString, ls), UseRegexLR),
                ParseType.CSS => ParseCSS(original, ReplaceValues(CssSelector, ls), ReplaceValues(AttributeName, ls)),
                ParseType.JSON => ParseJSON(original, ReplaceValues(JsonField, ls), JTokenParsing),
                ParseType.REGEX => ParseREGEX(original, ReplaceValues(RegexString, ls), ReplaceValues(RegexOutput, ls), DotMatches, CaseSensitive),
                _ => throw new NotImplementedException()
            };

            if (!Recursive && Type == ParseType.CSS)
            {
                list = new List <string> {
                    list[CssElementIndex]
                };
            }

            InsertVariable(ls, IsCapture, Recursive, list, VariableName, Prefix, Suffix, EncodeOutput, CreateEmpty);
        }
Example #12
0
 /// <summary>
 /// Executes the actual block logic.
 /// </summary>
 public virtual Task Process(LSGlobals ls)
 {
     ls.BotData.Logger.Log($">> Executing Block {Label} <<", LogColors.ChromeYellow);
     return(Task.CompletedTask);
 }
Example #13
0
        /// <summary>
        /// Replaces variables in a given input string.
        /// </summary>
        public static string ReplaceValues(string original, LSGlobals ls)
        {
            if (original == null)
            {
                return(string.Empty);
            }

            var data    = ls.BotData;
            var globals = ls.Globals;

            if (!original.Contains("<") && !original.Contains(">"))
            {
                return(original);
            }

            var previous = "";
            var output   = original;

            do
            {
                previous = output;

                // Replace all the fixed quantities
                output = output.Replace("<INPUT>", data.Line.Data);
                output = output.Replace("<STATUS>", data.STATUS);
                output = output.Replace("<SOURCE>", data.SOURCE);
                output = output.Replace("<COOKIES>", data.COOKIES.AsString());
                output = output.Replace("<HEADERS>", data.HEADERS.AsString());
                output = output.Replace("<RESPONSECODE>", data.RESPONSECODE.AsString());
                output = output.Replace("<ADDRESS>", data.ADDRESS);
                output = output.Replace("<RETRIES>", data.Line.Retries.ToString());

                var lastCaptchaInfo = data.TryGetObject <CaptchaInfo>("lastCaptchaInfo");
                if (lastCaptchaInfo is not null)
                {
                    output = output.Replace("<CAPTCHAID>", lastCaptchaInfo.Id.ToString());
                }

                // TODO: Readd this
                // output = output.Replace("<BOTNUM>", data.BotNumber.ToString());

                if (data.Proxy != null)
                {
                    output = output.Replace("<PROXY>", data.Proxy.ToString());
                }

                // Get all the inner (max. 1 level of nesting) variables
                var matches = Regex.Matches(output, @"<([^<>]*)>");

                foreach (Match match in matches)
                {
                    var full = match.Groups[0].Value;
                    var m    = match.Groups[1].Value;

                    // Parse the variable name
                    var name = Regex.Match(m, @"^[^\[\{\(]*").Value;

                    // Try to get the variable (first local, then global, then if none was found go to the next iteration)
                    // We don't throw an error here because it could be some HTML or XML code e.g. <br> that triggers this, and we dont' want to spam the user with unneeded errors
                    var v = GetVariables(data).Get(name);

                    if (v == null)
                    {
                        if (name == "COOKIES")
                        {
                            v = new DictionaryOfStringsVariable(data.COOKIES)
                            {
                                Name = name
                            };
                        }
                        else if (name == "HEADERS")
                        {
                            v = new DictionaryOfStringsVariable(data.HEADERS)
                            {
                                Name = name
                            };
                        }
                        else
                        {
                            v = globals.Get(name);
                        }
                    }

                    if (v == null)
                    {
                        continue;
                    }

                    // Parse the arguments
                    var args = m.Replace(name, "");

                    switch (v)
                    {
                    case StringVariable:
                        output = output.Replace(full, v.AsString());
                        break;

                    case ListOfStringsVariable:

                        // If it's just the list name, replace it with its string representation
                        if (string.IsNullOrEmpty(args))
                        {
                            output = output.Replace(full, v.AsString());
                            break;
                        }

                        var index = 0;
                        int.TryParse(ParseArguments(args, '[', ']')[0], out index);
                        var item = GetListItem(v.AsListOfStrings(), index);     // Can return null

                        if (item != null)
                        {
                            output = output.Replace(full, item);
                        }
                        break;

                    case DictionaryOfStringsVariable:

                        var dict = v.AsDictionaryOfStrings();

                        if (args.Contains("(") && args.Contains(")"))
                        {
                            var key = ParseArguments(args, '(', ')')[0];

                            if (dict.ContainsKey(key))
                            {
                                output = output.Replace(full, dict[key]);
                            }
                        }
                        else if (args.Contains("{") && args.Contains("}"))
                        {
                            var value = ParseArguments(args, '{', '}')[0];

                            if (dict.ContainsValue(value))
                            {
                                output = output.Replace(full, dict.First(kvp => kvp.Value == value).Key);
                            }
                        }
                        else     // If it's just the dictionary name, replace it with its string representation
                        {
                            output = output.Replace(full, v.AsString());
                            break;
                        }
                        break;
                    }
                }
            }while (original.Contains("<") && original.Contains(">") && output != previous);

            return(output);
        }
Example #14
0
        /// <summary>
        /// Executes a line of the script.
        /// </summary>
        /// <param name="data">The BotData needed for variable replacement</param>
        public async Task TakeStep(LSGlobals ls)
        {
            var data = ls.BotData;

            // TODO: Refactor this with a properly written policy
            // If we have a custom status without forced continue OR we have a status that is not NONE or SUCCESS or CUSTOM
            if (!CanContinue(data))
            {
                i = lines.Length; // Go to the end
                return;
            }

TAKELINE:

            CurrentLine = lines[i];

            // Skip comments and blank lines
            if (IsEmptyOrCommentOrDisabled(CurrentLine))
            {
                i++; // Go to the next
                goto TAKELINE;
            }

            // Lookahead to compact lines. We don't use CompressedLines to be able to provide the line number for errors
            var lookahead = 0;

            // Join the line with the following ones if it's indented
            while (i + 1 + lookahead < lines.Length)
            {
                var nextLine = lines[i + 1 + lookahead];

                if (nextLine.StartsWith(" ") || nextLine.StartsWith("\t"))
                {
                    CurrentLine += $" {nextLine.Trim()}";
                }
                else
                {
                    break;
                }

                lookahead++;
            }

            try
            {
                // If Block -> Process Block
                if (BlockParser.IsBlock(CurrentLine))
                {
                    BlockBase block = null;
                    try
                    {
                        block              = BlockParser.Parse(CurrentLine);
                        CurrentBlock       = block.Label;
                        data.ExecutionInfo = $"Executing block: {block.Label}";

                        if (!block.Disabled)
                        {
                            await block.Process(ls);
                        }
                    }
                    catch (Exception ex)
                    {
                        // We log the error message
                        var errorMessage = data.Providers.GeneralSettings.VerboseMode ? ex.ToString() : ex.Message;
                        data.Logger.Log("ERROR: " + errorMessage, LogColors.Tomato);

                        // Stop the execution only if the block is vital for the execution of the script (requests)
                        // This way we prevent the interruption of the script and an endless retry cycle e.g. if we fail to parse a response given a specific input
                        if (block != null && block is BlockRequest)
                        {
                            data.STATUS = "ERROR";
                            throw new BlockProcessingException(ex.Message);
                        }
                    }
                }

                // If Command -> Process Command
                else if (CommandParser.IsCommand(CurrentLine))
                {
                    try
                    {
                        var action = CommandParser.Parse(CurrentLine, ls);
                        action?.Invoke();
                    }
                    catch (Exception ex)
                    {
                        var errorMessage = data.Providers.GeneralSettings.VerboseMode ? ex.ToString() : ex.Message;
                        data.Logger.Log("ERROR: " + errorMessage, LogColors.Tomato);
                        data.STATUS = "ERROR";
                    }
                }

                // Try to Process Flow Control
                else
                {
                    var cfLine = CurrentLine;
                    var token  = LineParser.ParseToken(ref cfLine, TokenType.Parameter, false); // This proceeds, so we have the cfLine ready for next parsing

                    switch (token.ToUpper())
                    {
                    case "IF":
                        // Check condition, if not true jump to line after first ELSE or ENDIF (check both at the same time on lines, not separately)
                        if (!ParseCheckCondition(ref cfLine, ls))
                        {
                            i = ScanFor(lines, i, true, new string[] { "ENDIF", "ELSE" });
                            data.Logger.Log($"Jumping to line {i + 1}", LogColors.White);
                        }
                        break;

                    case "ELSE":
                        // Here jump to ENDIF because you are coming from an IF and you don't need to process the ELSE
                        i = ScanFor(lines, i, true, new string[] { "ENDIF" });
                        data.Logger.Log($"Jumping to line {i + 1}", LogColors.White);
                        break;

                    case "ENDIF":
                        break;

                    case "WHILE":
                        // Check condition, if false jump to first index after ENDWHILE
                        if (!ParseCheckCondition(ref cfLine, ls))
                        {
                            i = ScanFor(lines, i, true, new string[] { "ENDWHILE" });
                            data.Logger.Log($"Jumping to line {i + 1}", LogColors.White);
                        }
                        break;

                    case "ENDWHILE":
                        // Jump back to the previous WHILE index
                        i = ScanFor(lines, i, false, new string[] { "WHILE" }) - 1;
                        data.Logger.Log($"Jumping to line {i + 1}", LogColors.White);
                        break;

                    case "JUMP":
                        var label = "";
                        try
                        {
                            label = LineParser.ParseToken(ref cfLine, TokenType.Label, true);
                            i     = ScanFor(lines, -1, true, new string[] { $"{label}" }) - 1;
                            data.Logger.Log($"Jumping to line {i + 2}", LogColors.White);
                        }
                        catch { throw new Exception($"No block with label {label} was found"); }
                        break;

                    case "BEGIN":
                        var beginToken = LineParser.ParseToken(ref cfLine, TokenType.Parameter, true);
                        switch (beginToken.ToUpper())
                        {
                        case "SCRIPT":
                            language = (ScriptingLanguage)LineParser.ParseEnum(ref cfLine, "LANGUAGE", typeof(ScriptingLanguage));
                            var end = 0;
                            try
                            {
                                end = ScanFor(lines, i, true, new string[] { "END" }) - 1;
                            }
                            catch
                            {
                                throw new Exception("No 'END SCRIPT' specified");
                            }

                            otherScript = string.Join(Environment.NewLine, lines.Skip(i + 1).Take(end - i));
                            i           = end;
                            data.Logger.Log($"Jumping to line {i + 2}", LogColors.White);
                            break;
                        }
                        break;

                    case "END":
                        var endToken = LineParser.ParseToken(ref cfLine, TokenType.Parameter, true);
                        switch (endToken.ToUpper())
                        {
                        case "SCRIPT":
                            LineParser.EnsureIdentifier(ref cfLine, "->");
                            LineParser.EnsureIdentifier(ref cfLine, "VARS");
                            var outputs = LineParser.ParseLiteral(ref cfLine, "OUTPUTS");

                            try
                            {
                                if (otherScript != string.Empty)
                                {
                                    RunScript(otherScript, language, outputs, data);
                                }
                            }
                            catch (Exception ex)
                            {
                                var errorMessage = data.Providers.GeneralSettings.VerboseMode ? ex.ToString() : ex.Message;
                                data.Logger.Log($"The script failed to be executed: {errorMessage}", LogColors.Tomato);
                            }
                            break;
                        }
                        break;

                    default:
                        break;
                    }
                }
            }
            catch (BlockProcessingException)
            {
                // Rethrow the Block Processing Exception so the error can be displayed in the view above
                throw;
            }
            catch (Exception e)
            {
                // Catch inner and throw line exception
                throw new Exception($"Parsing Exception on line {i + 1}: {e.Message}");
            }

            i += 1 + lookahead;
        }
Example #15
0
        /// <summary>
        /// Replaces variables recursively, expanding lists or dictionaries with jolly indices.
        /// </summary>
        public static List <string> ReplaceValuesRecursive(string original, LSGlobals ls)
        {
            var data      = ls.BotData;
            var globals   = ls.Globals;
            var toReplace = new List <string>();

            // Regex parse the syntax <LIST[*]>
            var matches   = Regex.Matches(original, @"<([^\[]*)\[\*\]>");
            var variables = new List <ListOfStringsVariable>();

            foreach (Match m in matches)
            {
                var name = m.Groups[1].Value;

                // Retrieve the variable
                var variable = GetVariables(data).Get(name);

                // If it's null, try to get it from the global variables
                if (variable == null)
                {
                    variable = globals.Get(name);

                    // If still null, there's nothing to replace, skip it
                    if (variable == null)
                    {
                        continue;
                    }
                }

                // Make sure it's a List of strings and add it to the list
                if (variable is ListOfStringsVariable list)
                {
                    variables.Add(list);
                }
            }

            // If there's no corresponding variable, just readd the input string and proceed with normal replacement
            if (variables.Count > 0)
            {
                // Example: we have 3 lists of sizes 3, 7 and 5. We need to take 7
                var max = variables.Max(v => v.AsListOfStrings().Count);

                for (var i = 0; i < max; i++)
                {
                    var replaced = original;

                    foreach (var variable in variables)
                    {
                        var list = variable.AsListOfStrings();
                        replaced = list.Count > i?replaced.Replace($"<{variable.Name}[*]>", list[i]) : replaced.Replace($"<{variable.Name}[*]>", "NULL");
                    }

                    toReplace.Add(replaced);
                }
                goto END;
            }

            // Regex parse the syntax <DICT(*)> (wildcard key -> returns list of all values)
            var match = Regex.Match(original, @"<([^\(]*)\(\*\)>");

            if (match.Success)
            {
                var full = match.Groups[0].Value;
                var name = match.Groups[1].Value;

                // Retrieve the dictionary
                var dict = GetVariables(data).Get <DictionaryOfStringsVariable>(name);

                if (dict == null)
                {
                    dict = globals.Get <DictionaryOfStringsVariable>(name);
                }

                // If there's no corresponding variable, just readd the input string and proceed with normal replacement
                if (dict == null)
                {
                    toReplace.Add(original);
                }
                else
                {
                    foreach (var item in dict.AsDictionaryOfStrings())
                    {
                        toReplace.Add(original.Replace(full, item.Value));
                    }
                }
                goto END;
            }

            // Regex parse the syntax <DICT{*}> (wildcard value -> returns list of all keys)
            match = Regex.Match(original, @"<([^\{]*)\{\*\}>");

            if (match.Success)
            {
                var full = match.Groups[0].Value;
                var name = match.Groups[1].Value;

                // Retrieve the dictionary
                var dict = GetVariables(data).Get <DictionaryOfStringsVariable>(name);

                if (dict == null)
                {
                    if (name == "COOKIES")
                    {
                        dict = new DictionaryOfStringsVariable(data.COOKIES)
                        {
                            Name = name
                        };
                    }
                    else if (name == "HEADERS")
                    {
                        dict = new DictionaryOfStringsVariable(data.HEADERS)
                        {
                            Name = name
                        };
                    }
                    else
                    {
                        dict = globals.Get <DictionaryOfStringsVariable>(name);
                    }
                }

                // If there's no corresponding variable, just readd the input string and proceed with normal replacement
                if (dict == null)
                {
                    toReplace.Add(original);
                }
                else
                {
                    foreach (var item in dict.AsDictionaryOfStrings())
                    {
                        toReplace.Add(original.Replace(full, item.Key));
                    }
                }
                goto END;
            }

            // If no other match was a success, it means there's no recursive value and we simply add the input to the list
            toReplace.Add(original);

END:
            // Now for each item in the list, do the normal replacement and return the replaced list of strings
            return(toReplace.Select(i => (string)ReplaceValues(i, ls)).ToList());
        }
Example #16
0
        public async Task Run()
        {
            // Build the C# script if in Stack or LoliCode mode
            if (config.Mode == ConfigMode.Stack || config.Mode == ConfigMode.LoliCode)
            {
                config.CSharpScript = config.Mode == ConfigMode.Stack
                    ? Stack2CSharpTranspiler.Transpile(config.Stack, config.Settings)
                    : Loli2CSharpTranspiler.Transpile(config.LoliCodeScript, config.Settings);
            }

            if (options.UseProxy && !options.TestProxy.Contains(':'))
            {
                throw new InvalidProxyException(options.TestProxy);
            }

            if (!options.PersistLog)
            {
                logger.Clear();
            }

            // Close any previously opened browsers
            if (lastPuppeteerBrowser != null)
            {
                await lastPuppeteerBrowser.CloseAsync();
            }

            if (lastSeleniumBrowser != null)
            {
                lastSeleniumBrowser.Quit();
            }

            options.Variables.Clear();
            IsRunning = true;
            cts       = new CancellationTokenSource();
            var sw = new Stopwatch();

            var wordlistType = RuriLibSettings.Environment.WordlistTypes.First(w => w.Name == options.WordlistType);
            var dataLine     = new DataLine(options.TestData, wordlistType);
            var proxy        = options.UseProxy ? Proxy.Parse(options.TestProxy, options.ProxyType) : null;

            var providers = new Bots.Providers(RuriLibSettings)
            {
                RNG = RNGProvider
            };

            if (!RuriLibSettings.RuriLibSettings.GeneralSettings.UseCustomUserAgentsList)
            {
                providers.RandomUA = RandomUAProvider;
            }

            // Build the BotData
            var data = new BotData(providers, config.Settings, logger, dataLine, proxy, options.UseProxy)
            {
                CancellationToken = cts.Token
            };

            using var httpClient = new HttpClient();
            data.SetObject("httpClient", httpClient);
            var runtime  = Python.CreateRuntime();
            var pyengine = runtime.GetEngine("py");
            var pco      = (PythonCompilerOptions)pyengine.GetCompilerOptions();

            pco.Module &= ~ModuleOptions.Optimized;
            data.SetObject("ironPyEngine", pyengine);
            data.AsyncLocker = new();

            dynamic globals = new ExpandoObject();

            var script = new ScriptBuilder()
                         .Build(config.CSharpScript, config.Settings.ScriptSettings, PluginRepo);

            logger.Log($"Sliced {dataLine.Data} into:");
            foreach (var slice in dataLine.GetVariables())
            {
                var sliceValue = data.ConfigSettings.DataSettings.UrlEncodeDataAfterSlicing
                    ? Uri.EscapeDataString(slice.AsString())
                    : slice.AsString();

                logger.Log($"{slice.Name}: {sliceValue}");
            }

            // Initialize resources
            Dictionary <string, ConfigResource> resources = new();

            // Resources will need to be disposed of
            foreach (var opt in config.Settings.DataSettings.Resources)
            {
                try
                {
                    resources[opt.Name] = opt switch
                    {
                        LinesFromFileResourceOptions x => new LinesFromFileResource(x),
                        RandomLinesFromFileResourceOptions x => new RandomLinesFromFileResource(x),
                        _ => throw new NotImplementedException()
                    };
                }
                catch
                {
                    logger.Log($"Could not create resource {opt.Name}", LogColors.Tomato);
                }
            }

            // Add resources to global variables
            globals.Resources = resources;
            var scriptGlobals = new ScriptGlobals(data, globals);

            // Set custom inputs
            foreach (var input in config.Settings.InputSettings.CustomInputs)
            {
                (scriptGlobals.input as IDictionary <string, object>).Add(input.VariableName, input.DefaultAnswer);
            }

            // [LEGACY] Set up the VariablesList
            if (config.Mode == ConfigMode.Legacy)
            {
                var slices = new List <Variable>();

                foreach (var slice in dataLine.GetVariables())
                {
                    var sliceValue = data.ConfigSettings.DataSettings.UrlEncodeDataAfterSlicing
                        ? Uri.EscapeDataString(slice.AsString())
                        : slice.AsString();

                    slices.Add(new StringVariable(sliceValue)
                    {
                        Name = slice.Name
                    });
                }

                var legacyVariables = new VariablesList(slices);

                foreach (var input in config.Settings.InputSettings.CustomInputs)
                {
                    legacyVariables.Set(new StringVariable(input.DefaultAnswer)
                    {
                        Name = input.VariableName
                    });
                }

                data.SetObject("legacyVariables", legacyVariables);
            }

            try
            {
                sw.Start();
                Started?.Invoke(this, EventArgs.Empty);

                if (config.Mode != ConfigMode.Legacy)
                {
                    var state = await script.RunAsync(scriptGlobals, null, cts.Token);

                    foreach (var scriptVar in state.Variables)
                    {
                        try
                        {
                            var type = DescriptorsRepository.ToVariableType(scriptVar.Type);

                            if (type.HasValue && !scriptVar.Name.StartsWith("tmp_"))
                            {
                                var variable = DescriptorsRepository.ToVariable(scriptVar.Name, scriptVar.Type, scriptVar.Value);
                                variable.MarkedForCapture = data.MarkedForCapture.Contains(scriptVar.Name);
                                options.Variables.Add(variable);
                            }
                        }
                        catch
                        {
                            // The type is not supported, e.g. it was generated using custom C# code and not blocks
                            // so we just disregard it
                        }
                    }
                }
                else
                {
                    // [LEGACY] Run the LoliScript in the old way
                    var loliScript = new LoliScript(config.LoliScript);
                    var lsGlobals  = new LSGlobals(data);

                    do
                    {
                        if (cts.IsCancellationRequested)
                        {
                            break;
                        }

                        await loliScript.TakeStep(lsGlobals);

                        options.Variables.Clear();
                        var legacyVariables = data.TryGetObject <VariablesList>("legacyVariables");
                        options.Variables.AddRange(legacyVariables.Variables);
                        options.Variables.AddRange(lsGlobals.Globals.Variables);
                    }while (loliScript.CanProceed);
                }
            }
            catch (OperationCanceledException)
            {
                data.STATUS = "ERROR";
                logger.Log($"Operation canceled", LogColors.Tomato);
            }
            catch (Exception ex)
            {
                data.STATUS = "ERROR";

                var logErrorMessage = RuriLibSettings.RuriLibSettings.GeneralSettings.VerboseMode
                    ? ex.ToString()
                    : ex.Message;

                logger.Log($"[{data.ExecutionInfo}] {ex.GetType().Name}: {logErrorMessage}", LogColors.Tomato);
                IsRunning = false;
                throw;
            }
            finally
            {
                sw.Stop();

                logger.Log($"BOT ENDED AFTER {sw.ElapsedMilliseconds} ms WITH STATUS: {data.STATUS}");

                // Save the browsers for later use
                lastPuppeteerBrowser = data.TryGetObject <Browser>("puppeteer");
                lastSeleniumBrowser  = data.TryGetObject <OpenQA.Selenium.WebDriver>("selenium");

                // Dispose stuff in data.Objects
                data.DisposeObjectsExcept(new[] { "puppeteer", "puppeteerPage", "puppeteerFrame", "selenium" });

                // Dispose resources
                foreach (var resource in resources.Where(r => r.Value is IDisposable)
                         .Select(r => r.Value).Cast <IDisposable>())
                {
                    resource.Dispose();
                }

                data.AsyncLocker.Dispose();
            }

            IsRunning = false;
            Stopped?.Invoke(this, EventArgs.Empty);
        }
Example #17
0
 /// <summary>
 /// Verifies if at least one of the provided conditions is true (after replacing).
 /// </summary>
 public static bool ReplaceAndVerifyAny(KeycheckCondition[] conditions, LSGlobals ls)
 => conditions.Any(c => ReplaceAndVerify(c, ls));
Example #18
0
 /// <summary>
 /// Replaces the values and verifies if a condition is true or false.
 /// </summary>
 public static bool ReplaceAndVerify(string left, Comparer comparer, string right, LSGlobals ls)
 => ReplaceAndVerify(new KeycheckCondition()
 {
     Left = left, Comparer = comparer, Right = right
 }, ls);
Example #19
0
        /// <summary>
        /// Gets the Action that needs to be executed.
        /// </summary>
        static internal Action Parse(string line, LSGlobals ls)
        {
            var data  = ls.BotData;
            var input = line.Trim();
            var field = LineParser.ParseToken(ref input, TokenType.Parameter, true).ToUpper();

            return(new Action(() =>
            {
                var name = "";
                var comparer = Comparer.EqualTo;

                switch (field)
                {
                case "COOKIE":
                    if (LineParser.Lookahead(ref input) == TokenType.Parameter)
                    {
                        comparer = (Comparer)LineParser.ParseEnum(ref input, "TYPE", typeof(Comparer));
                    }

                    name = LineParser.ParseLiteral(ref input, "NAME");

                    for (var i = 0; i < data.COOKIES.Count; i++)
                    {
                        var curr = data.COOKIES.ToList()[i].Key;

                        if (Condition.ReplaceAndVerify(curr, comparer, name, ls))
                        {
                            data.COOKIES.Remove(curr);
                        }
                    }
                    break;

                case "VAR":
                    if (LineParser.Lookahead(ref input) == TokenType.Parameter)
                    {
                        comparer = (Comparer)LineParser.ParseEnum(ref input, "TYPE", typeof(Comparer));
                    }

                    name = LineParser.ParseLiteral(ref input, "NAME");
                    BlockBase.GetVariables(data).RemoveAll(comparer, name, ls);
                    break;

                case "GVAR":
                    if (LineParser.Lookahead(ref input) == TokenType.Parameter)
                    {
                        comparer = (Comparer)LineParser.ParseEnum(ref input, "TYPE", typeof(Comparer));
                    }

                    name = LineParser.ParseLiteral(ref input, "NAME");

                    try
                    {
                        ls.Globals.RemoveAll(comparer, name, ls);
                    }
                    catch
                    {
                    }
                    break;

                default:
                    throw new ArgumentException($"Invalid identifier {field}");
                }

                data.Logger.Log($"DELETE command executed on field {field}", LogColors.White);
            }));
        }
Example #20
0
        /// <inheritdoc />
        public override async Task Process(LSGlobals ls)
        {
            var data = ls.BotData;
            await base.Process(ls);

            var localInputStrings = ReplaceValuesRecursive(InputString, ls);
            var outputs           = new List <string>();

            for (var i = 0; i < localInputStrings.Count; i++)
            {
                var localInputString = localInputStrings[i];
                var outputString     = "";

                switch (FunctionType)
                {
                case Function.Constant:
                    outputString = localInputString;
                    break;

                case Function.Base64Encode:
                    outputString = Base64Converter.ToBase64String(Encoding.UTF8.GetBytes(localInputString));
                    break;

                case Function.Base64Decode:
                    outputString = Encoding.UTF8.GetString(Base64Converter.ToByteArray(localInputString));
                    break;

                case Function.HTMLEntityEncode:
                    outputString = WebUtility.HtmlEncode(localInputString);
                    break;

                case Function.HTMLEntityDecode:
                    outputString = WebUtility.HtmlDecode(localInputString);
                    break;

                case Function.Hash:
                    outputString = GetHash(localInputString, HashType, InputBase64).ToLower();
                    break;

                case Function.HMAC:
                    outputString = Hmac(localInputString, HashType, ReplaceValues(HmacKey, ls), InputBase64, KeyBase64, HmacBase64);
                    break;

                case Function.Translate:
                    outputString = localInputString;
                    foreach (var entry in TranslationDictionary.OrderBy(e => e.Key.Length).Reverse())
                    {
                        if (outputString.Contains(entry.Key))
                        {
                            outputString = outputString.Replace(entry.Key, entry.Value);
                            if (StopAfterFirstMatch)
                            {
                                break;
                            }
                        }
                    }
                    break;

                case Function.DateToUnixTime:
                    outputString = localInputString.ToDateTime(DateFormat).ToUnixTime().ToString();
                    break;

                case Function.Length:
                    outputString = localInputString.Length.ToString();
                    break;

                case Function.ToLowercase:
                    outputString = localInputString.ToLower();
                    break;

                case Function.ToUppercase:
                    outputString = localInputString.ToUpper();
                    break;

                case Function.Replace:
                    outputString = UseRegex
                            ? Regex.Replace(localInputString, ReplaceValues(ReplaceWhat, ls), ReplaceValues(ReplaceWith, ls))
                            : localInputString.Replace(ReplaceValues(ReplaceWhat, ls), ReplaceValues(ReplaceWith, ls));
                    break;

                case Function.RegexMatch:
                    outputString = Regex.Match(localInputString, ReplaceValues(RegexMatch, ls)).Value;
                    break;

                case Function.Unescape:
                    outputString = Regex.Unescape(localInputString);
                    break;

                case Function.URLEncode:
                    // The maximum allowed Uri size is 2083 characters, we use 2080 as a precaution
                    outputString = string.Join("", SplitInChunks(localInputString, 2080).Select(s => Uri.EscapeDataString(s)));
                    break;

                case Function.URLDecode:
                    outputString = Uri.UnescapeDataString(localInputString);
                    break;

                case Function.UnixTimeToDate:
                    outputString = long.Parse(localInputString).ToDateTimeUtc().ToString(DateFormat);
                    break;

                case Function.CurrentUnixTime:
                    outputString = DateTime.UtcNow.ToUnixTime().ToString();
                    break;

                case Function.UnixTimeToISO8601:
                    outputString = long.Parse(localInputString).ToDateTimeUtc().ToISO8601();
                    break;

                case Function.RandomNum:
                    var min             = int.Parse(ReplaceValues(RandomMin, ls));
                    var max             = int.Parse(ReplaceValues(RandomMax, ls));
                    var randomNumString = data.Random.Next(min, max).ToString();
                    outputString = RandomZeroPad ? randomNumString.PadLeft(max.ToString().Length, '0') : randomNumString;
                    break;

                case Function.RandomString:
                    outputString = localInputString;
                    outputString = Regex.Replace(outputString, @"\?l", m => _lowercase[data.Random.Next(_lowercase.Length)].ToString());
                    outputString = Regex.Replace(outputString, @"\?u", m => _uppercase[data.Random.Next(_uppercase.Length)].ToString());
                    outputString = Regex.Replace(outputString, @"\?d", m => _digits[data.Random.Next(_digits.Length)].ToString());
                    outputString = Regex.Replace(outputString, @"\?s", m => _symbols[data.Random.Next(_symbols.Length)].ToString());
                    outputString = Regex.Replace(outputString, @"\?h", m => _hex[data.Random.Next(_hex.Length)].ToString());
                    outputString = Regex.Replace(outputString, @"\?a", m => _allChars[data.Random.Next(_allChars.Length)].ToString());
                    outputString = Regex.Replace(outputString, @"\?m", m => _udChars[data.Random.Next(_udChars.Length)].ToString());
                    outputString = Regex.Replace(outputString, @"\?n", m => _ldChars[data.Random.Next(_ldChars.Length)].ToString());
                    outputString = Regex.Replace(outputString, @"\?i", m => _ludChars[data.Random.Next(_ludChars.Length)].ToString());
                    outputString = Regex.Replace(outputString, @"\?f", m => _upperlwr[data.Random.Next(_upperlwr.Length)].ToString());
                    break;

                case Function.Ceil:
                    outputString = Math.Ceiling(decimal.Parse(localInputString, _style, _provider)).ToString();
                    break;

                case Function.Floor:
                    outputString = Math.Floor(decimal.Parse(localInputString, _style, _provider)).ToString();
                    break;

                case Function.Round:
                    outputString = Math.Round(decimal.Parse(localInputString, _style, _provider), 0, MidpointRounding.AwayFromZero).ToString();
                    break;

                case Function.Compute:
                    outputString = new DataTable().Compute(localInputString.Replace(',', '.'), null).ToString();
                    break;

                case Function.CountOccurrences:
                    outputString = CountStringOccurrences(localInputString, StringToFind).ToString();
                    break;

                case Function.ClearCookies:
                    data.COOKIES.Clear();
                    break;

                case Function.RSAEncrypt:
                    outputString = Crypto.RSAEncrypt(
                        localInputString,
                        ReplaceValues(RsaN, ls),
                        ReplaceValues(RsaE, ls),
                        RsaOAEP
                        );
                    break;

                /*
                 * case Function.RSADecrypt:
                 * outputString = Crypto.RSADecrypt(
                 *  localInputString,
                 *  ReplaceValues(RsaN, data),
                 *  ReplaceValues(RsaD, data),
                 *  RsaOAEP
                 *  );
                 * break;
                 */

                case Function.RSAPKCS1PAD2:
                    outputString = Crypto.RSAPkcs1Pad2(
                        localInputString,
                        ReplaceValues(RsaN, ls),
                        ReplaceValues(RsaE, ls)
                        );
                    break;

                case Function.Delay:
                    try { Thread.Sleep(int.Parse(localInputString)); } catch { }
                    break;

                case Function.CharAt:
                    outputString = localInputString.ToCharArray()[int.Parse(ReplaceValues(CharIndex, ls))].ToString();
                    break;

                case Function.Substring:
                    outputString = localInputString.Substring(int.Parse(ReplaceValues(SubstringIndex, ls)), int.Parse(ReplaceValues(SubstringLength, ls)));
                    break;

                case Function.ReverseString:
                    var charArray = localInputString.ToCharArray();
                    Array.Reverse(charArray);
                    outputString = new string(charArray);
                    break;

                case Function.Trim:
                    outputString = localInputString.Trim();
                    break;

                case Function.GetRandomUA:
                    outputString = data.Providers.RandomUA.Generate();
                    break;

                case Function.AESEncrypt:
                    outputString = Crypto.AESEncrypt(localInputString, ReplaceValues(AesKey, ls),
                                                     ReplaceValues(AesIV, ls), AesMode, AesPadding);
                    break;

                case Function.AESDecrypt:
                    outputString = Crypto.AESDecrypt(localInputString, ReplaceValues(AesKey, ls),
                                                     ReplaceValues(AesIV, ls), AesMode, AesPadding);
                    break;

                case Function.PBKDF2PKCS5:
                    outputString = Crypto.PBKDF2PKCS5(localInputString, ReplaceValues(KdfSalt, ls),
                                                      KdfSaltSize, KdfIterations, KdfKeySize, KdfAlgorithm);
                    break;
                }

                data.Logger.Log($"Executed function {FunctionType} on input {localInputString} with outcome {outputString}", LogColors.GreenYellow);

                // Add to the outputs
                outputs.Add(outputString);
            }

            var isList = outputs.Count > 1 || InputString.Contains("[*]") || InputString.Contains("(*)") || InputString.Contains("{*}");

            InsertVariable(ls, IsCapture, isList, outputs, VariableName, "", "", false, true);
        }
        /// <inheritdoc />
        public override async Task Process(LSGlobals ls)
        {
            var data = ls.BotData;
            await base.Process(ls);

            var browser = data.TryGetObject <WebDriver>("selenium");

            if (browser == null && Action != BrowserAction.Open)
            {
                throw new Exception("Open a browser first!");
            }

            var     replacedInput = ReplaceValues(Input, ls);
            Actions keyActions    = null;

            switch (Action)
            {
            case BrowserAction.Open:
                OpenBrowser(data);
                UpdateSeleniumData(data);
                break;

            case BrowserAction.Close:
                browser.Close();
                data.SetObject("selenium", null);
                break;

            case BrowserAction.Quit:
                browser.Quit();
                data.SetObject("selenium", null);
                break;

            case BrowserAction.ClearCookies:
                browser.Manage().Cookies.DeleteAllCookies();
                break;

            case BrowserAction.SendKeys:
                keyActions = new Actions(browser);
                foreach (var s in replacedInput.Split(new string[] { "||" }, StringSplitOptions.None))
                {
                    switch (s)
                    {
                    case "<TAB>":
                        keyActions.SendKeys(Keys.Tab);
                        break;

                    case "<ENTER>":
                        keyActions.SendKeys(Keys.Enter);
                        break;

                    case "<BACKSPACE>":
                        keyActions.SendKeys(Keys.Backspace);
                        break;

                    case "<ESC>":
                        keyActions.SendKeys(Keys.Escape);
                        break;

                    default:
                        // List of available keys https://github.com/SeleniumHQ/selenium/blob/master/dotnet/src/webdriver/Keys.cs
                        var keyFields     = typeof(Keys).GetFields();
                        var matchingField = keyFields.FirstOrDefault(f =>
                                                                     $"<{f.Name}>".Equals(s, StringComparison.InvariantCultureIgnoreCase));

                        if (matchingField != null)
                        {
                            keyActions.SendKeys(matchingField.GetValue(null).ToString());
                        }
                        else
                        {
                            keyActions.SendKeys(s);
                        }
                        break;
                    }
                }
                keyActions.Perform();
                Thread.Sleep(1000);
                if (replacedInput.Contains("<ENTER>") || replacedInput.Contains("<BACKSPACE>"))     // These might lead to a page change
                {
                    UpdateSeleniumData(data);
                }
                break;

            case BrowserAction.Screenshot:
                var screenshotFile = Utils.GetScreenshotPath(data);
                browser.GetScreenshot().SaveAsFile(screenshotFile);
                break;

            case BrowserAction.OpenNewTab:
                ((IJavaScriptExecutor)browser).ExecuteScript("window.open();");
                browser.SwitchTo().Window(browser.WindowHandles.Last());
                break;

            case BrowserAction.SwitchToTab:
                browser.SwitchTo().Window(browser.WindowHandles[int.Parse(replacedInput)]);
                UpdateSeleniumData(data);
                break;

            case BrowserAction.CloseCurrentTab:
                ((IJavaScriptExecutor)browser).ExecuteScript("window.close();");
                break;

            case BrowserAction.Refresh:
                browser.Navigate().Refresh();
                break;

            case BrowserAction.Back:
                browser.Navigate().Back();
                break;

            case BrowserAction.Forward:
                browser.Navigate().Forward();
                break;

            case BrowserAction.Maximize:
                browser.Manage().Window.Maximize();
                break;

            case BrowserAction.Minimize:
                browser.Manage().Window.Minimize();
                break;

            case BrowserAction.FullScreen:
                browser.Manage().Window.FullScreen();
                break;

            case BrowserAction.SetWidth:
                browser.Manage().Window.Size = new Size(int.Parse(replacedInput), browser.Manage().Window.Size.Height);
                break;

            case BrowserAction.SetHeight:
                browser.Manage().Window.Size = new Size(browser.Manage().Window.Size.Width, int.Parse(replacedInput));
                break;

            case BrowserAction.DOMtoSOURCE:
                data.SOURCE = browser.FindElement(By.TagName("body")).GetAttribute("innerHTML");
                break;

            case BrowserAction.GetCookies:
                foreach (var cookie in browser.Manage().Cookies.AllCookies)
                {
                    if (!string.IsNullOrWhiteSpace(cookie.Name))
                    {
                        data.COOKIES[cookie.Name] = cookie.Value;
                    }
                }
                break;

            case BrowserAction.SetCookies:
                var baseURL = Regex.Match(replacedInput, "^(?:https?:\\/\\/)?(?:[^@\\/\n]+@)?([^:\\/?\n]+)").Groups[1].Value;
                foreach (var cookie in data.COOKIES)
                {
                    try
                    {
                        browser.Manage().Cookies.AddCookie(new Cookie(cookie.Key, cookie.Value, baseURL, "/", DateTime.MaxValue));
                    }
                    catch
                    {
                    }
                }
                break;

            case BrowserAction.SwitchToDefault:
                browser.SwitchTo().DefaultContent();
                break;

            case BrowserAction.SwitchToAlert:
                browser.SwitchTo().Alert();
                break;

            case BrowserAction.SwitchToParentFrame:
                browser.SwitchTo().ParentFrame();
                break;
            }

            data.Logger.Log(string.Format("Executed browser action {0} on input {1}", Action, replacedInput), LogColors.White);
        }
Example #22
0
 /// <summary>
 /// Adds a list variable with the given value.
 /// </summary>
 protected static void InsertVariable(LSGlobals ls, bool isCapture, IEnumerable <string> values, string variableName,
                                      string prefix = "", string suffix = "", bool urlEncode = false, bool createEmpty = true)
 => InsertVariable(ls, isCapture, true, values, variableName, prefix, suffix, urlEncode, createEmpty);
Example #23
0
 /// <summary>
 /// Parses a literal value from a line.
 /// </summary>
 /// <param name="input">The reference to the line of code</param>
 /// <param name="label">Debug information about the expected literal</param>
 /// <param name="replace">Whether to perform variable replacement in the literal</param>
 /// <returns>The literal without the leading and trailing double quotes</returns>
 public static string ParseLiteral(ref string input, string label, bool replace = false, LSGlobals ls = null)
 {
     try
     {
         return(replace
             ? BlockBase.ReplaceValues(ParseToken(ref input, TokenType.Literal, true), ls)
             : ParseToken(ref input, TokenType.Literal, true));
     }
     catch
     {
         throw new ArgumentException($"Expected Literal value for '{label}'");
     }
 }
Example #24
0
        /// <inheritdoc />
        public override async Task Process(LSGlobals ls)
        {
            var data = ls.BotData;
            await base.Process(ls);

            var provider = data.Providers.Captcha;

            data.Logger.Log("WARNING! This block is obsolete and WILL BE REMOVED IN THE FUTURE! Use the SOLVECAPTCHA block!", LogColors.Tomato);
            data.Logger.Log("Downloading image...", LogColors.White);

            var localUrl       = ReplaceValues(Url, ls);
            var captchaFile    = Utils.GetCaptchaPath(data);
            var screenshotFile = Utils.GetScreenshotPath(data);

            if (Base64)
            {
                var bytes = Convert.FromBase64String(localUrl);
                using var imageFile = new FileStream(captchaFile, FileMode.Create);
                imageFile.Write(bytes, 0, bytes.Length);
                imageFile.Flush();
            }
            else if (SendScreenshot && File.Exists(screenshotFile))
            {
                using var image = new Bitmap(screenshotFile);
                image.Save(captchaFile);
            }
            else
            {
                // Try to download the captcha
                try
                {
                    var standardOptions = new StandardHttpRequestOptions
                    {
                        CustomCookies = data.COOKIES,
                        CustomHeaders = new Dictionary <string, string>
                        {
                            { "User-Agent", UserAgent },
                            { "Accept", "*/*" },
                            { "Pragma", "no-cache" },
                            { "Accept-Language", "en-US,en;q=0.8" }
                        },
                        Method = HttpMethod.GET,
                        Url    = localUrl,
                        TimeoutMilliseconds = 10000
                    };

                    // Back up the old values
                    var oldAddress      = data.ADDRESS;
                    var oldSource       = data.SOURCE;
                    var oldResponseCode = data.RESPONSECODE;
                    var oldRawSource    = data.RAWSOURCE;

                    // Request the captcha
                    data.Logger.Enabled = false;
                    await RuriLib.Blocks.Requests.Http.Methods.HttpRequestStandard(data, standardOptions);

                    data.Logger.Enabled = true;

                    // Save the image
                    File.WriteAllBytes(captchaFile, data.RAWSOURCE);

                    // Put the old values back
                    data.ADDRESS      = oldAddress;
                    data.SOURCE       = oldSource;
                    data.RAWSOURCE    = oldRawSource;
                    data.RESPONSECODE = oldResponseCode;
                }
                catch (Exception ex)
                {
                    data.Logger.Enabled = true;
                    data.Logger.Log(ex.Message, LogColors.Tomato);
                    throw;
                }
            }

            // Now the captcha is inside the file at path 'captchaFile'

            var response = "";
            var bitmap   = new Bitmap(captchaFile);

            try
            {
                var converter = new ImageConverter();
                var bytes     = (byte[])converter.ConvertTo(bitmap, typeof(byte[]));

                var captchaResponse = await provider.SolveImageCaptchaAsync(Convert.ToBase64String(bytes));

                response = captchaResponse.Response;
            }
            catch (Exception ex)
            {
                data.Logger.Log(ex.Message, LogColors.Tomato);
                throw;
            }
            finally
            {
                bitmap.Dispose();
            }

            data.Logger.Log($"Succesfully got the response: {response}", LogColors.GreenYellow);

            if (VariableName != string.Empty)
            {
                GetVariables(data).Set(new StringVariable(response)
                {
                    Name = VariableName
                });
                data.Logger.Log($"Response stored in variable: {VariableName}.", LogColors.White);
            }
        }
        /// <inheritdoc />
        public override async Task Process(LSGlobals ls)
        {
            var data = ls.BotData;
            await base.Process(ls);

            var browser = data.TryGetObject <WebDriver>("selenium");

            if (browser == null)
            {
                throw new Exception("Open a browser first!");
            }

            // Find the element
            IWebElement element = null;
            ReadOnlyCollection <IWebElement> elements = null;

            if (Action != ElementAction.WaitForElement)
            {
                elements = FindElements(browser, ReplaceValues(ElementString, ls));

                if (ElementIndex + 1 > elements.Count)
                {
                    throw new Exception("Cannot find the element on the page");
                }
            }

            var replacedInput = ReplaceValues(Input, ls);
            var outputs       = new List <string>();

            switch (Action)
            {
            case ElementAction.Clear:
                element.Clear();
                break;

            case ElementAction.SendKeys:
                element.SendKeys(replacedInput);
                break;

            case ElementAction.Click:
                element.Click();
                UpdateSeleniumData(data);
                break;

            case ElementAction.Submit:
                element.Submit();
                UpdateSeleniumData(data);
                break;

            case ElementAction.SelectOptionByText:
                new SelectElement(element).SelectByText(replacedInput);
                break;

            case ElementAction.SelectOptionByIndex:
                new SelectElement(element).SelectByIndex(int.Parse(replacedInput));
                break;

            case ElementAction.SelectOptionByValue:
                new SelectElement(element).SelectByValue(replacedInput);
                break;

            case ElementAction.GetText:
                if (Recursive)
                {
                    foreach (var elem in elements)
                    {
                        outputs.Add(elem.Text);
                    }
                }
                else
                {
                    outputs.Add(element.Text);
                }
                break;

            case ElementAction.GetAttribute:
                if (Recursive)
                {
                    foreach (var elem in elements)
                    {
                        outputs.Add(elem.GetAttribute(replacedInput));
                    }
                }
                else
                {
                    outputs.Add(element.GetAttribute(replacedInput));
                }
                break;

            case ElementAction.IsDisplayed:
                outputs.Add(element.Displayed.ToString());
                break;

            case ElementAction.IsEnabled:
                outputs.Add(element.Enabled.ToString());
                break;

            case ElementAction.IsSelected:
                outputs.Add(element.Selected.ToString());
                break;

            case ElementAction.LocationX:
                outputs.Add(element.Location.X.ToString());
                break;

            case ElementAction.LocationY:
                outputs.Add(element.Location.Y.ToString());
                break;

            case ElementAction.SizeX:
                outputs.Add(element.Size.Width.ToString());
                break;

            case ElementAction.SizeY:
                outputs.Add(element.Size.Height.ToString());
                break;

            case ElementAction.Screenshot:
                var image = TakeElementScreenshot(browser, element);
                image.Save(Utils.GetScreenshotPath(data));
                image.Dispose();
                break;

            case ElementAction.ScreenshotBase64:
                var img = TakeElementScreenshot(browser, element);
                var ms  = new MemoryStream();
                img.Save(ms, ImageFormat.Jpeg);
                var base64 = Convert.ToBase64String(ms.ToArray());
                outputs.Add(base64);
                img.Dispose();
                ms.Dispose();
                break;

            case ElementAction.SwitchToFrame:
                browser.SwitchTo().Frame(element);
                break;

            case ElementAction.WaitForElement:
                var waited  = 0;    // Currently waited milliseconds
                var timeout = 10000;
                try
                {
                    timeout = int.Parse(replacedInput) * 1000;
                }
                catch
                {
                }
                var found = false;

                while (waited < timeout)
                {
                    try
                    {
                        FindElements(browser, ReplaceValues(ElementString, ls));
                        element = elements[0];
                        found   = true;
                        break;
                    }
                    catch
                    {
                        waited += 200;
                        await Task.Delay(200);
                    }
                }

                if (!found)
                {
                    throw new TimeoutException("Timed out while waiting for the element");
                }

                break;

            case ElementAction.SendKeysHuman:
                foreach (var c in replacedInput)
                {
                    element.SendKeys(c.ToString());
                    await Task.Delay(data.Random.Next(100, 300));
                }
                break;
            }

            data.Logger.Log(string.Format("Executed action {0} on the element with input {1}", Action, replacedInput), LogColors.White);

            if (outputs.Count > 0)
            {
                InsertVariable(ls, IsCapture, Recursive, outputs, OutputVariable, "", "", false, true);
            }
        }
Example #26
0
        /// <inheritdoc />
        public override async Task Process(LSGlobals ls)
        {
            var data = ls.BotData;
            await base.Process(ls);

            var      replacedInput = ReplaceValues(InputString, ls);
            var      variablesList = GetVariables(data);
            Variable variableToAdd = null;
            var      logColor      = IsCapture ? LogColors.Tomato : LogColors.Yellow;

            switch (Group)
            {
            case UtilityGroup.List:
                var list  = variablesList.Get <ListOfStringsVariable>(ListName)?.AsListOfStrings();
                var list2 = variablesList.Get <ListOfStringsVariable>(SecondListName)?.AsListOfStrings();
                var item  = ReplaceValues(ListItem, ls);
                var index = int.Parse(ReplaceValues(ListIndex, ls));

                switch (ListAction)
                {
                case ListAction.Create:
                    variableToAdd = new ListOfStringsVariable(new List <string>());
                    break;

                case ListAction.Length:
                    variableToAdd = new StringVariable(list.Count.ToString());
                    break;

                case ListAction.Join:
                    variableToAdd = new StringVariable(string.Join(Separator, list));
                    break;

                case ListAction.Sort:
                    var sorted = list.Select(e => e).ToList();         // Clone the list so we don't edit the original one

                    if (Numeric)
                    {
                        var nums = sorted.Select(e => double.Parse(e, CultureInfo.InvariantCulture)).ToList();
                        nums.Sort();
                        sorted = nums.Select(e => e.ToString()).ToList();
                    }
                    else
                    {
                        sorted.Sort();
                    }

                    if (!Ascending)
                    {
                        sorted.Reverse();
                    }

                    variableToAdd = new ListOfStringsVariable(sorted);
                    break;

                case ListAction.Concat:
                    variableToAdd = new ListOfStringsVariable(list.Concat(list2).ToList());
                    break;

                case ListAction.Zip:
                    variableToAdd = new ListOfStringsVariable(list.Zip(list2, (a, b) => a + b).ToList());
                    break;

                case ListAction.Map:
                    variableToAdd = new DictionaryOfStringsVariable(list.Zip(list2, (k, v) => new { k, v }).ToDictionary(x => x.k, x => x.v));
                    break;

                case ListAction.Add:
                    // Handle negative indices
                    index = index switch
                    {
                        0 => 0,
                        < 0 => index + list.Count,
                        _ => index
                    };
                    list.Insert(index, item);
                    break;

                case ListAction.Remove:
                    // Handle negative indices
                    index = index switch
                    {
                        0 => 0,
                        < 0 => index + list.Count,
                        _ => index
                    };
                    list.RemoveAt(index);
                    break;

                case ListAction.RemoveValues:
                    variableToAdd = new ListOfStringsVariable(list.Where(l => !Condition.Verify(new KeycheckCondition
                    {
                        Left     = ReplaceValues(l, ls),
                        Comparer = ListElementComparer,
                        Right    = ListComparisonTerm
                    })).ToList());
                    break;

                case ListAction.RemoveDuplicates:
                    variableToAdd = new ListOfStringsVariable(list.Distinct().ToList());
                    break;

                case ListAction.Random:
                    variableToAdd = new StringVariable(list[data.Random.Next(list.Count)]);
                    break;

                case ListAction.Shuffle:
                    // This makes a copy of the original list
                    var listCopy = new List <string>(list);
                    listCopy.Shuffle(data.Random);
                    variableToAdd = new ListOfStringsVariable(listCopy);
                    break;

                default:
                    break;
                }
                data.Logger.Log($"Executed action {ListAction} on list {ListName}", logColor);
                break;

            case UtilityGroup.Variable:
                string single = variablesList.Get <StringVariable>(VarName).AsString();
                switch (VarAction)
                {
                case VarAction.Split:
                    variableToAdd = new ListOfStringsVariable(single.Split(new string[]
                                                                           { ReplaceValues(SplitSeparator, ls) }, StringSplitOptions.None).ToList());
                    break;
                }
                data.Logger.Log($"Executed action {VarAction} on variable {VarName}", logColor);
                break;

            case UtilityGroup.Conversion:
                var conversionInputBytes = replacedInput.ConvertFrom(ConversionFrom);
                var conversionResult     = conversionInputBytes.ConvertTo(ConversionTo);
                variableToAdd = new StringVariable(conversionResult);
                data.Logger.Log($"Executed conversion {ConversionFrom} to {ConversionTo} on input {replacedInput} with outcome {conversionResult}", logColor);
                break;

            case UtilityGroup.File:
                var file = ReplaceValues(FilePath, ls);
                FileUtils.ThrowIfNotInCWD(file);

                switch (FileAction)
                {
                case FileAction.Exists:
                    variableToAdd = new StringVariable(File.Exists(file).ToString());
                    break;

                case FileAction.Read:
                    lock (FileLocker.GetHandle(file))
                        variableToAdd = new StringVariable(File.ReadAllText(file));
                    break;

                case FileAction.ReadLines:
                    lock (FileLocker.GetHandle(file))
                        variableToAdd = new ListOfStringsVariable(File.ReadAllLines(file).ToList());
                    break;

                case FileAction.Write:
                    FileUtils.CreatePath(file);
                    lock (FileLocker.GetHandle(file))
                        File.WriteAllText(file, replacedInput.Unescape());
                    break;

                case FileAction.WriteLines:
                    FileUtils.CreatePath(file);
                    lock (FileLocker.GetHandle(file))
                        File.WriteAllLines(file, ReplaceValuesRecursive(InputString, ls).Select(i => i.Unescape()));
                    break;

                case FileAction.Append:
                    FileUtils.CreatePath(file);
                    lock (FileLocker.GetHandle(file))
                        File.AppendAllText(file, replacedInput.Unescape());
                    break;

                case FileAction.AppendLines:
                    FileUtils.CreatePath(file);
                    lock (FileLocker.GetHandle(file))
                        File.AppendAllLines(file, ReplaceValuesRecursive(InputString, ls).Select(i => i.Unescape()));
                    break;

                case FileAction.Copy:
                    var fileCopyLocation = ReplaceValues(InputString, ls);
                    FileUtils.ThrowIfNotInCWD(fileCopyLocation);
                    FileUtils.CreatePath(fileCopyLocation);
                    lock (FileLocker.GetHandle(file))
                        lock (FileLocker.GetHandle(fileCopyLocation))
                            File.Copy(file, fileCopyLocation);
                    break;

                case FileAction.Move:
                    var fileMoveLocation = ReplaceValues(InputString, ls);
                    FileUtils.ThrowIfNotInCWD(fileMoveLocation);
                    FileUtils.CreatePath(fileMoveLocation);
                    lock (FileLocker.GetHandle(file))
                        lock (FileLocker.GetHandle(fileMoveLocation))
                            File.Move(file, fileMoveLocation);
                    break;

                case FileAction.Delete:
                    // No deletion if the file is in use (DB/OpenBullet.db cannot be deleted but instead DB/OpenBullet-BackupCopy.db)
                    // If another process is just reading the file it will be deleted
                    lock (FileLocker.GetHandle(file))
                        File.Delete(file);
                    break;
                }

                data.Logger.Log($"Executed action {FileAction} on file {file}", logColor);
                break;

            case UtilityGroup.Folder:
                var folder = ReplaceValues(FolderPath, ls);
                FileUtils.ThrowIfNotInCWD(folder);

                switch (FolderAction)
                {
                case FolderAction.Exists:
                    variableToAdd = new StringVariable(Directory.Exists(folder).ToString());
                    break;

                case FolderAction.Create:
                    variableToAdd = new StringVariable(Directory.CreateDirectory(folder).ToString());
                    break;

                case FolderAction.Delete:
                    Directory.Delete(folder, true);
                    break;
                }

                data.Logger.Log($"Executed action {FolderAction} on folder {folder}", logColor);
                break;

            default:
                break;
            }

            if (variableToAdd is not null)
            {
                variableToAdd.Name             = VariableName;
                variableToAdd.MarkedForCapture = IsCapture;
                variablesList.Set(variableToAdd);
            }
        }
Example #27
0
 /// <summary>
 /// Removes all variables that meet a given a condition.
 /// </summary>
 public void RemoveAll(Comparer comparer, string name, LSGlobals ls)
 => Variables.RemoveAll(v => Condition.ReplaceAndVerify(v.Name, comparer, name, ls));
Example #28
0
 /// <summary>
 /// Adds a single variable with the given value.
 /// </summary>
 protected static void InsertVariable(LSGlobals ls, bool isCapture, string value, string variableName,
                                      string prefix = "", string suffix = "", bool urlEncode = false, bool createEmpty = true)
 => InsertVariable(ls, isCapture, false, new string[] { value }, variableName, prefix, suffix, urlEncode, createEmpty);
Example #29
0
        /// <summary>
        /// Gets the Action that needs to be executed.
        /// </summary>
        static internal Action Parse(string line, LSGlobals ls)
        {
            var data  = ls.BotData;
            var input = line.Trim();
            var field = LineParser.ParseToken(ref input, TokenType.Parameter, true).ToUpper();

            return(new Action(() =>
            {
                switch (field)
                {
                case "SOURCE":
                    data.SOURCE = LineParser.ParseLiteral(ref input, "SOURCE", true, ls);
                    break;

                case "STATUS":
                    data.STATUS = LineParser.ParseToken(ref input, TokenType.Parameter, true);

                    // E.g. user wrote SET STATUS CUSTOM "TEST"
                    if (data.STATUS == "CUSTOM" && !string.IsNullOrEmpty(input))
                    {
                        data.STATUS = LineParser.ParseLiteral(ref input, "CUSTOM STATUS");
                    }
                    break;

                case "RESPONSECODE":
                    data.RESPONSECODE = LineParser.ParseInt(ref input, "RESPONSECODE");
                    break;

                case "COOKIE":
                    var name = LineParser.ParseLiteral(ref input, "NAME", true, ls);
                    data.COOKIES.Add(name, LineParser.ParseLiteral(ref input, "VALUE", true, ls));
                    break;

                case "ADDRESS":
                    data.ADDRESS = LineParser.ParseLiteral(ref input, "ADDRESS", true, ls);
                    break;

                case "USEPROXY":
                    var use = LineParser.ParseToken(ref input, TokenType.Parameter, true).ToUpper();

                    if (use == "TRUE")
                    {
                        data.UseProxy = true;
                    }
                    else if (use == "FALSE")
                    {
                        data.UseProxy = false;
                    }
                    break;

                case "PROXY":
                    var prox = LineParser.ParseLiteral(ref input, "PROXY", true, ls);
                    data.Proxy = Proxy.Parse(prox);
                    break;

                case "PROXYTYPE":
                    data.Proxy.Type = (ProxyType)LineParser.ParseEnum(ref input, "PROXYTYPE", typeof(ProxyType));
                    break;

                case "DATA":
                    data.Line.Data = LineParser.ParseLiteral(ref input, "DATA", true, ls);
                    break;

                case "VAR":
                    var varName = LineParser.ParseLiteral(ref input, "NAME", true, ls);
                    var varValue = LineParser.ParseLiteral(ref input, "VALUE", true, ls);
                    BlockBase.GetVariables(data).Set(new StringVariable(varValue)
                    {
                        Name = varName
                    });
                    break;

                case "CAP":
                    var capName = LineParser.ParseLiteral(ref input, "NAME", true, ls);
                    var capValue = LineParser.ParseLiteral(ref input, "VALUE", true, ls);
                    BlockBase.GetVariables(data).Set(new StringVariable(capValue)
                    {
                        Name = capName
                    });
                    data.MarkForCapture(capName);
                    break;

                case "GVAR":
                    try
                    {
                        var globalVarName = LineParser.ParseLiteral(ref input, "NAME", true, ls);
                        var globalVarValue = LineParser.ParseLiteral(ref input, "VALUE", true, ls);
                        ls.Globals.Set(new StringVariable(globalVarValue)
                        {
                            Name = globalVarName
                        });
                    }
                    catch
                    {
                    }
                    break;

                case "NEWGVAR":
                    try
                    {
                        var globalVarName = LineParser.ParseLiteral(ref input, "NAME", true, ls);
                        var globalVarValue = LineParser.ParseLiteral(ref input, "VALUE", true, ls);
                        ls.Globals.SetIfNew(new StringVariable(globalVarValue)
                        {
                            Name = globalVarName
                        });
                    }
                    catch
                    {
                    }
                    break;

                case "GCOOKIES":
                    ls.GlobalCookies.Clear();
                    foreach (var cookie in data.COOKIES)
                    {
                        ls.GlobalCookies.Add(cookie.Key, cookie.Value);
                    }
                    break;

                default:
                    throw new ArgumentException($"Invalid identifier {field}");
                }

                data.Logger.Log($"SET command executed on field {field}", LogColors.White);
            }));
        }
Example #30
0
 /// <summary>
 /// Replaces variables in all items of a list.
 /// </summary>
 public static List <string> ReplaceValues(List <string> original, LSGlobals ls)
 => original.Select(i => ReplaceValues(i, ls)).ToList();