/// <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}'"), });
/// <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}'"); } }
/// <summary> /// Gets a command Action from a command line. /// </summary> /// <param name="line">The command line</param> /// <param name="data">The BotData needed for variable replacement</param> /// <returns>The Action that needs to be executed</returns> public static Action Parse(string line, BotData data) { // 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"); } switch ((CommandName)Enum.Parse(typeof(CommandName), identifier, true)) { case CommandName.PRINT: return(new Action(() => data.Log(new LogEntry(BlockBase.ReplaceValues(input, data), Colors.White)))); case CommandName.SET: return(SetParser.Parse(input, data)); case CommandName.DELETE: return(DeleteParser.Parse(input, data)); case CommandName.MOUSEACTION: return(MouseActionParser.Parse(input, data)); case CommandName.STOP: return(new Action(() => { data.Worker?.CancelAsync(); data.Log(new LogEntry("Stoped!", Colors.OrangeRed)); })); case CommandName.ForceStop: return(new Action(() => { data.Worker?.Abort(); data.Log(new LogEntry("Force Stoped!", Colors.OrangeRed)); })); default: throw new ArgumentException($"Invalid identifier '{identifier}'"); } }
/// <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> /// <param name="data">The BotData needed for variable replacement</param> /// <returns>The literal without the leading and trailing double quotes</returns> public static string ParseLiteral(ref string input, string label, bool replace = false, BotData data = null) { try { if (replace) { return(BlockBase.ReplaceValues(ParseToken(ref input, TokenType.Literal, true), data)); } else { return(ParseToken(ref input, TokenType.Literal, true)); } } catch { throw new ArgumentException($"Expected Literal value for '{label}'"); } }
/// <summary> /// Replaces the values and verifies if a condition is true or false. /// </summary> /// <param name="kcCond">The keycheck condition struct</param> /// <param name="data">The BotData used for variable replacement</param> /// <returns>Whether the comparison is verified or not.</returns> public static bool ReplaceAndVerify(KeycheckCondition kcCond, BotData data) { 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, data); // The left-hand term can accept recursive values like <LIST[*]> var r = BlockBase.ReplaceValues(kcCond.Right, data); // 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.GreaterOrEqual: 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.LessThanOrEqual: 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); } }
/// <summary> /// Checks all the Keys in the KeyChain. /// </summary> /// <param name="data">The BotData used for variable replacement</param> /// <returns>Whether the KeyChain was triggered or not</returns> public bool CheckKeys(BotData data) { switch (Mode) { case KeychainMode.OR: foreach (var key in Keys) { if (key.CheckKey(data)) { data.Log(new LogEntry(string.Format("Found 'OR' Key {0} {1} {2}", BlockBase.TruncatePretty(BlockBase.ReplaceValues(key.LeftTerm, data), 20), key.Comparer.ToString(), BlockBase.ReplaceValues(key.RightTerm, data)), Colors.White)); return(true); } } return(false); case KeychainMode.AND: foreach (var key in Keys) { if (!key.CheckKey(data)) { return(false); } else { data.Log(new LogEntry(string.Format("Found 'AND' Key {0} {1} {2}", BlockBase.TruncatePretty(BlockBase.ReplaceValues(key.LeftTerm, data), 20), key.Comparer.ToString(), BlockBase.ReplaceValues(key.RightTerm, data)), Colors.White)); } } return(true); } return(false); }
public override void Process(BotData data) { base.Process(data); string email = BlockBase.ReplaceValues(this.Email, data); string password = BlockBase.ReplaceValues(this.Password, data); MegaApiClient megaApiClient = new MegaApiClient(); try { megaApiClient.Login(email, password); bool flag = !megaApiClient.IsLoggedIn; if (flag) { throw new Exception(); } IEnumerator <INode> enumerator = megaApiClient.GetNodes().GetEnumerator(); List <string> list = new List <string>(); int num = 0; while (enumerator.MoveNext() && num < this.MaxFilesCaptured) { bool flag2 = enumerator.Current.Name != null; if (flag2) { list.Add(enumerator.Current.Name); num++; } } IAccountInformation accountInformation = megaApiClient.GetAccountInformation(); BlockBase.InsertVariable(data, this.IsCapture, accountInformation.UsedQuota.ToString(), "USEDQUOTA", "", "", false, false); BlockBase.InsertVariable(data, this.IsCapture, accountInformation.TotalQuota.ToString(), "TOTALQUOTA", "", "", false, false); BlockBase.InsertVariable(data, this.IsCapture, list, this.VariableName, "", "", false, false); data.Status = RuriLib.BotStatus.SUCCESS; } catch (Exception ex) { data.Log(ex.Message); data.Status = RuriLib.BotStatus.FAIL; } }
/// <summary> /// Runs a script with a different language inside the LoliScript. /// </summary> /// <param name="script">The script as a string with linebreaks</param> /// <param name="language">The language of the script</param> /// <param name="outputs">The variables that should be extracted from the script's scope and set into the BotData local variables</param> /// <param name="data">The BotData needed for variable replacement</param> private void RunScript(string script, ScriptingLanguage language, string outputs, BotData data, string jsFilePath = "") { // Set the console output to stringwriter var sw = new StringWriter(); Console.SetOut(sw); Console.SetError(sw); jsFilePath = BlockBase.ReplaceValues(jsFilePath, data); if (jsFilePath != string.Empty && File.Exists(jsFilePath)) { script += File.ReadAllText(jsFilePath); } // Parse variables to get out List <string> outVarList = new List <string>(); if (outputs != string.Empty) { try { outVarList = outputs.Split(',').Select(x => x.Trim()).ToList(); } catch { } } var start = DateTime.Now; try { switch (language) { case ScriptingLanguage.JavaScript: var taskExecuteJs = Task.Run(() => { object jsRetValue = null; bool disposeEngine = false; JavascriptContext context = null; if (disposeEngine = data.JsEngine == null) { context = new JavascriptContext(); JsEngine.SetParameter(context, data); } else { context = data.JsEngine.GetOrCreateEngine(data); } // Execute JS try { jsRetValue = context.Run(script); } catch (JavascriptException ex) { throw new Exception($"Executing js error {ex.Message}\nline: {ex.Line}\nStart column:{ex.StartColumn}"); } // Print results to log data.Log(new LogEntry($"DEBUG LOG: {sw}", Colors.White)); // Get variables out data.Log(new LogEntry($"Parsing {outVarList.Count} variables", Colors.White)); foreach (var name in outVarList) { try { //Add it to the variables and print info var value = context.GetParameter(name); var isArray = value.GetType().IsArray || value is string[] || value.GetType().Name.Contains("Dictionary"); if (isArray) { try { data.Variables.Set(new CVar(name, CVar.VarType.List, (List <string>)value)); } catch (Exception ex) { data.Log(new LogEntry("[SET VARS] ERROR: " + ex.Message, Colors.Yellow)); } } else { data.Variables.Set(new CVar(name, CVar.VarType.Single, value.ToString())); } data.Log(new LogEntry($"SET VARIABLE {name} WITH VALUE {value}", Colors.Yellow)); } catch { data.Log(new LogEntry($"COULD NOT FIND VARIABLE {name}", Colors.Tomato)); } } if (disposeEngine) { context.Dispose(); } //Print other info if (jsRetValue != null && !jsRetValue.GetType().Name.Contains("Dictionary")) { data.Log(new LogEntry($"Return value: {jsRetValue}", Colors.White)); } }); taskExecuteJs.Wait(); taskExecuteJs.Dispose(); break; case ScriptingLanguage.IronPython: // Initialize the engine var runtime = Python.CreateRuntime(); var pyengine = runtime.GetEngine("py"); PythonCompilerOptions pco = (PythonCompilerOptions)pyengine.GetCompilerOptions(); pco.Module &= ~ModuleOptions.Optimized; //var pyengine = Python.CreateEngine(); var scope = pyengine.CreateScope(); var code = pyengine.CreateScriptSourceFromString(script); // Add in all the variables foreach (var variable in data.Variables.All) { try { scope.SetVariable(variable.Name, variable.Value); } catch { } } // Execute it var result = code.Execute(scope); //var result = pyengine.Execute(script, scope); // Print the logs data.Log(new LogEntry($"DEBUG LOG: {sw}", Colors.White)); // Get variables out data.Log(new LogEntry($"Parsing {outVarList.Count} variables", Colors.White)); foreach (var name in outVarList) { try { // Add it to the variables and print info var value = scope.GetVariable(name); data.Variables.Set(new CVar(name, (value.GetType() == typeof(string[])) ? CVar.VarType.List : CVar.VarType.Single, value.ToString())); data.Log(new LogEntry($"SET VARIABLE {name} WITH VALUE {value}", Colors.Yellow)); } catch { data.Log(new LogEntry($"COULD NOT FIND VARIABLE {name}", Colors.Tomato)); } } // Print other info if (result != null) { data.Log(new LogEntry($"Completion value: {result}", Colors.White)); } break; default: break; } data.Log(new LogEntry($"Execution completed in {(DateTime.Now - start).TotalSeconds} seconds", Colors.GreenYellow)); } catch (Exception e) { data.Log(new LogEntry($"[ERROR] INFO: {e.Message}", Colors.White)); } finally { var standardOutput = new StreamWriter(Console.OpenStandardOutput()); var standardError = new StreamWriter(Console.OpenStandardError()); standardOutput.AutoFlush = true; standardError.AutoFlush = true; Console.SetOut(standardOutput); Console.SetError(standardError); } }
/// <summary> /// Gets the Action that needs to be executed. /// </summary> /// <param name="line">The data line to parse</param> /// <param name="data">The BotData needed for variable replacement</param> /// <returns>The Action to execute</returns> public static Action Parse(string line, BotData data) { var input = line.Trim(); var field = LineParser.ParseToken(ref input, TokenType.Parameter, true).ToUpper(); return(new Action(() => { switch (field) { case "SOURCE": data.ResponseSource = LineParser.ParseLiteral(ref input, "SOURCE", true, data); break; case "STATUS": data.Status = (BotStatus)LineParser.ParseEnum(ref input, "STATUS", typeof(BotStatus)); if (data.Status == BotStatus.CUSTOM) { data.CustomStatus = LineParser.ParseLiteral(ref input, "CUSTOM STATUS"); } break; case "RESPONSECODE": data.ResponseCode = LineParser.ParseInt(ref input, "RESPONSECODE").ToString(); break; case "COOKIE": var name = LineParser.ParseLiteral(ref input, "NAME", true, data); data.Cookies.Add(name, LineParser.ParseLiteral(ref input, "VALUE", true, data)); break; case "ADDRESS": data.Address = LineParser.ParseLiteral(ref input, "ADDRESS", true, data); break; case "USEPROXY": var use = LineParser.ParseToken(ref input, TokenType.Parameter, true).ToUpper(); if (use == "TRUE") { data.UseProxies = true; } else if (use == "FALSE") { data.UseProxies = false; } break; case "PROXY": var prox = LineParser.ParseLiteral(ref input, "PROXY", true, data); data.Proxy = new CProxy(BlockBase.ReplaceValues(prox, data), data.Proxy == null ? ProxyType.Http : data.Proxy.Type); break; case "PROXYTYPE": data.Proxy.Type = (ProxyType)LineParser.ParseEnum(ref input, "PROXYTYPE", typeof(ProxyType)); break; case "DATA": data.Data = new CData(LineParser.ParseLiteral(ref input, "DATA", true, data), new WordlistType()); break; case "VAR": { var cVar = new CVar( LineParser.ParseLiteral(ref input, "NAME", true, data), LineParser.ParseLiteral(ref input, "VALUE", true, data), false ); try { cVar.Hidden = LineParser.ParseToken(ref input, TokenType.Parameter, false) .ToBoolean(); } catch { } data.Variables.Set(cVar); } break; case "CAP": { var cVar = new CVar( LineParser.ParseLiteral(ref input, "NAME", true, data), LineParser.ParseLiteral(ref input, "VALUE", true, data), true ); try { cVar.Hidden = LineParser.ParseToken(ref input, TokenType.Parameter, false) .ToBoolean(); } catch { } data.Variables.Set(cVar); } break; case "GVAR": try { var cVar = new CVar( LineParser.ParseLiteral(ref input, "NAME", true, data), LineParser.ParseLiteral(ref input, "VALUE", true, data), false ); try { cVar.Hidden = LineParser.ParseToken(ref input, TokenType.Parameter, false) .ToBoolean(); } catch { } data.GlobalVariables.Set(cVar); } catch { } break; case "NEWGVAR": try { var cVar = new CVar( LineParser.ParseLiteral(ref input, "NAME", true, data), LineParser.ParseLiteral(ref input, "VALUE", true, data), false ); try { cVar.Hidden = LineParser.ParseToken(ref input, TokenType.Parameter, false) .ToBoolean(); } catch { } data.GlobalVariables.SetNew(cVar); } catch { } break; case "GCOOKIES": data.GlobalCookies.Clear(); foreach (var cookie in data.Cookies) { data.GlobalCookies.Add(cookie.Key, cookie.Value); } break; default: throw new ArgumentException($"Invalid identifier {field}"); } data.Log(new LogEntry($"SET command executed on field {field}", Colors.White)); })); }
/// <summary> /// Gets the Action that needs to be executed. /// </summary> /// <param name="line">The data line to parse</param> /// <param name="data">The BotData needed for variable replacement</param> /// <returns>The Action to execute</returns> public static Action Parse(string line, BotData data) { // Trim the line var input = line.Trim(); // Initialize the action chain Actions actions = null; try { actions = new Actions(data.Driver); } catch { throw new Exception("No Browser initialized!"); } // Build it var offsetX = 0; var offsetY = 0; var point1X = 0; var point1Y = 0; var point2X = 0; var point2Y = 0; var key = ""; var gravity = 1; var wind = 1; var qty = 0; IWebElement elem1 = null; IWebElement elem2 = null; Line newLine = null; while (input != string.Empty) { var parsed = LineParser.ParseToken(ref input, TokenType.Parameter, true).ToUpper(); switch (parsed) { case "SPAWN": // Spawn a div in a certain position so you can hook to it later via id if (LineParser.Lookahead(ref input) == TokenType.Integer) { point1X = LineParser.ParseInt(ref input, "X"); point1Y = LineParser.ParseInt(ref input, "Y"); } else if (LineParser.Lookahead(ref input) == TokenType.Literal) { point1X = int.Parse(BlockBase.ReplaceValues(LineParser.ParseLiteral(ref input, "X"), data)); point1Y = int.Parse(BlockBase.ReplaceValues(LineParser.ParseLiteral(ref input, "Y"), data)); } SpawnDiv(data.Driver, point1X, point1Y, LineParser.ParseLiteral(ref input, "ID")); break; case "CLICK": if (!LineParser.CheckIdentifier(ref input, "ELEMENT")) { actions.Click(); } else { actions.Click(ParseElement(ref input, data)); } break; case "CLICKANDHOLD": if (!LineParser.CheckIdentifier(ref input, "ELEMENT")) { actions.ClickAndHold(); } else { actions.ClickAndHold(ParseElement(ref input, data)); } break; case "RIGHTCLICK": if (!LineParser.CheckIdentifier(ref input, "ELEMENT")) { actions.ContextClick(); } else { actions.ContextClick(ParseElement(ref input, data)); } break; case "DOUBLECLICK": if (!LineParser.CheckIdentifier(ref input, "ELEMENT")) { actions.DoubleClick(); } else { actions.DoubleClick(ParseElement(ref input, data)); } break; case "DRAGANDDROP": elem1 = ParseElement(ref input, data); LineParser.ParseToken(ref input, TokenType.Arrow, true); elem2 = ParseElement(ref input, data); actions.DragAndDrop(elem1, elem2); break; case "DRAGANDDROPWITHOFFSET": if (LineParser.Lookahead(ref input) == TokenType.Integer) { offsetX = LineParser.ParseInt(ref input, "OFFSET X"); offsetY = LineParser.ParseInt(ref input, "OFFSET Y"); } else if (LineParser.Lookahead(ref input) == TokenType.Literal) { offsetX = int.Parse(BlockBase.ReplaceValues(LineParser.ParseLiteral(ref input, "OFFSET X"), data)); offsetY = int.Parse(BlockBase.ReplaceValues(LineParser.ParseLiteral(ref input, "OFFSET Y"), data)); } actions.DragAndDropToOffset(ParseElement(ref input, data), offsetX, offsetY); break; case "KEYDOWN": key = LineParser.ParseLiteral(ref input, "KEY", true, data); if (!LineParser.CheckIdentifier(ref input, "ELEMENT")) { actions.KeyDown(key); } else { actions.KeyDown(ParseElement(ref input, data), key); } break; case "KEYUP": key = LineParser.ParseLiteral(ref input, "KEY", true, data); if (!LineParser.CheckIdentifier(ref input, "ELEMENT")) { actions.KeyUp(key); } else { actions.KeyUp(ParseElement(ref input, data), key); } break; case "MOVEBY": if (LineParser.Lookahead(ref input) == TokenType.Integer) { offsetX = LineParser.ParseInt(ref input, "OFFSET X"); offsetY = LineParser.ParseInt(ref input, "OFFSET Y"); } else if (LineParser.Lookahead(ref input) == TokenType.Literal) { offsetX = int.Parse(BlockBase.ReplaceValues(LineParser.ParseLiteral(ref input, "OFFSET X"), data)); offsetY = int.Parse(BlockBase.ReplaceValues(LineParser.ParseLiteral(ref input, "OFFSET Y"), data)); } actions.MoveByOffset(offsetX, offsetY); break; case "MOVETO": actions.MoveToElement(ParseElement(ref input, data)); break; case "RELEASE": if (!LineParser.CheckIdentifier(ref input, "ELEMENT")) { actions.Release(); } else { actions.Release(ParseElement(ref input, data)); } break; case "SENDKEYS": key = LineParser.ParseLiteral(ref input, "KEY", true, data); if (!LineParser.CheckIdentifier(ref input, "ELEMENT")) { actions.SendKeys(key); } else { actions.SendKeys(ParseElement(ref input, data), key); } break; case "DRAWPOINTS": offsetX = LineParser.ParseInt(ref input, "MAX WIDTH"); offsetY = LineParser.ParseInt(ref input, "MAX HEIGHT"); var amount = LineParser.ParseInt(ref input, "AMOUNT"); Random rand = new Random(); var previousx = 0; var previousy = 0; // Move to the first point actions.MoveToElement(data.Driver.FindElementByTagName("body"), point1X, point1Y); List <Point> points = new List <Point>(); for (int i = 0; i < amount; i++) { var x = rand.Next(0, offsetX); var y = rand.Next(0, offsetY); actions.MoveByOffset(x - previousx, y - previousy); previousx = x; previousy = y; points.Add(new Point(x, y)); } if (data.GlobalSettings.Selenium.DrawMouseMovement) { DrawRedDots(data.Driver, points.ToArray(), 5); } break; case "DRAWLINE": // DRAWLINE 10 10 -> 20 20 if (LineParser.Lookahead(ref input) == TokenType.Integer) { point1X = LineParser.ParseInt(ref input, "X1"); point1Y = LineParser.ParseInt(ref input, "Y1"); LineParser.ParseToken(ref input, TokenType.Arrow, true); point2X = LineParser.ParseInt(ref input, "X2"); point2Y = LineParser.ParseInt(ref input, "Y2"); } // DRAWLINE "10" "20" -> "<MY_X>" "<MY_Y>" else if (LineParser.Lookahead(ref input) == TokenType.Literal) { point1X = int.Parse(BlockBase.ReplaceValues(LineParser.ParseLiteral(ref input, "X1"), data)); point1Y = int.Parse(BlockBase.ReplaceValues(LineParser.ParseLiteral(ref input, "Y1"), data)); LineParser.ParseToken(ref input, TokenType.Arrow, true); point2X = int.Parse(BlockBase.ReplaceValues(LineParser.ParseLiteral(ref input, "X2"), data)); point2Y = int.Parse(BlockBase.ReplaceValues(LineParser.ParseLiteral(ref input, "Y2"), data)); } else { elem1 = ParseElement(ref input, data); point1X = elem1.Location.X; point1Y = elem1.Location.Y; LineParser.ParseToken(ref input, TokenType.Arrow, true); elem2 = ParseElement(ref input, data); point2X = elem2.Location.X; point2Y = elem2.Location.Y; } LineParser.EnsureIdentifier(ref input, ":"); qty = LineParser.ParseInt(ref input, "QUANTITY"); // Move to the first point actions.MoveToElement(data.Driver.FindElementByTagName("body"), point1X, point1Y); newLine = new Line(new Point(point1X, point1Y), new Point(point2X, point2Y)); if (data.GlobalSettings.Selenium.DrawMouseMovement) { DrawRedDots(data.Driver, newLine.getPoints(qty), 5); } foreach (var p in newLine.getOffsets(qty)) { actions.MoveByOffset(p.X, p.Y); } break; case "DRAWLINEHUMAN": // DRAWLINEHUMAN 10 10 -> 20 20 if (LineParser.Lookahead(ref input) == TokenType.Integer) { point1X = LineParser.ParseInt(ref input, "X1"); point1Y = LineParser.ParseInt(ref input, "Y1"); LineParser.ParseToken(ref input, TokenType.Arrow, true); point2X = LineParser.ParseInt(ref input, "X2"); point2Y = LineParser.ParseInt(ref input, "Y2"); } // DRAWLINEHUMAN "10" "20" -> "<MY_X>" "<MY_Y>" else if (LineParser.Lookahead(ref input) == TokenType.Literal) { point1X = int.Parse(BlockBase.ReplaceValues(LineParser.ParseLiteral(ref input, "X1"), data)); point1Y = int.Parse(BlockBase.ReplaceValues(LineParser.ParseLiteral(ref input, "Y1"), data)); LineParser.ParseToken(ref input, TokenType.Arrow, true); point2X = int.Parse(BlockBase.ReplaceValues(LineParser.ParseLiteral(ref input, "X2"), data)); point2Y = int.Parse(BlockBase.ReplaceValues(LineParser.ParseLiteral(ref input, "Y2"), data)); } else { elem1 = ParseElement(ref input, data); point1X = elem1.Location.X; point1Y = elem1.Location.Y; LineParser.ParseToken(ref input, TokenType.Arrow, true); elem2 = ParseElement(ref input, data); point2X = elem2.Location.X; point2Y = elem2.Location.Y; } LineParser.EnsureIdentifier(ref input, ":"); qty = LineParser.ParseInt(ref input, "QUANTITY"); if (LineParser.Lookahead(ref input) == TokenType.Integer) { gravity = LineParser.ParseInt(ref input, "GRAVITY"); wind = LineParser.ParseInt(ref input, "WIND"); } // Move to the first point actions.MoveToElement(data.Driver.FindElementByTagName("body"), point1X, point1Y); newLine = new Line(new Point(point1X, point1Y), new Point(point2X, point2Y)); var array = newLine.HumanWindMouse(point1X, point1Y, point2X, point2Y, gravity, wind, 1); var shrinked = ShrinkArray(array, qty); if (data.GlobalSettings.Selenium.DrawMouseMovement) { DrawRedDots(data.Driver, shrinked, 5); } foreach (var p in GetOffsets(shrinked)) { actions.MoveByOffset(p.X, p.Y); } break; } } return(new Action(() => { actions.Build(); actions.Perform(); data.Log(new LogEntry("Executed Mouse Actions", Colors.White)); })); }