38 private readonly List<Action<PuppeteerClient>> _workflows =
new List<Action<PuppeteerClient>>();
42 private List<(
string Endpoint,
object Parameters,
string NextResultName)?> _workflowStates {
get;
set; } =
new List<(string, object, string)?>();
46 private bool _customEndpoint {
get;
set; } =
false;
50 private ApiEndpoint _apiEndpoint;
54 private string _endpoint {
get;
set; }
58 private object _parameters {
get;
set; }
62 internal ContentEncoding _contentEncoding = ContentEncoding.Json;
66 private string _name {
get;
set; }
70 private string _nextResultName {
get;
set; }
74 private string _saveFile {
get;
set; }
79 private readonly List<(
string Name,
object Result,
int Iteration,
string TargetId)> _executionResults =
new List<(
string Name,
object Result,
int Iteration,
string TargetId)>();
87 private int _currentIteration {
get;
set; }
91 internal Dictionary<string, string> _headers =
new Dictionary<string, string>();
95 private int _timeoutMs = 30000;
99 private int _pruneMs = 3_000;
103 private int _maxConnections {
get;
set; }
107 private int _hPixels {
get;
set; }
111 private int _vPixels {
get;
set; }
115 private string _attribute {
get;
set; }
119 private string _value {
get;
set; }
123 private string _text {
get;
set; }
127 private string _apiBase {
get;
set; } =
null;
135 internal string _currentTargetId {
get;
set; }
139 private Dictionary<string, Func<PuppeteerCommunicator, IDictionary<string, object>, string, Task<object>>> endpointMap {
get;
set; }
144 private Func<bool> _loopCondition {
get;
set; }
148 private string _loopType {
get;
set; }
152 private int _whileLoopTimeoutMs {
get;
set; }
156 private int _whileLoopMaxIterations {
get;
set; }
163 internal PuppeteerClient()
174 endpointMap =
new Dictionary<string, Func<PuppeteerCommunicator, IDictionary<string, object>, string, Task<object>>>
176 [RESTHelper.Endpoints[ApiEndpoint.Back]] = async (c, p, s) =>
178 return await c.Back(s).ConfigureAwait(
false);
180 [RESTHelper.Endpoints[ApiEndpoint.CaptureVisibleTab]] = async (c, p, s) =>
182 var parameters =
new Dictionary<string, object> { {
"format",
"jpeg" } };
183 if (p.ContainsKey(
"clip"))
185 dynamic format = p.ContainsKey(
"imageFormat") ? p[
"imageFormat"] :
"JPEG";
186 var clip = p[
"clip"] as IDictionary<string, object>;
189 double x = clip.ContainsKey(
"x") ? Convert.ToDouble(clip[
"x"]) : 0;
190 double y = clip.ContainsKey(
"y") ? Convert.ToDouble(clip[
"y"]) : 0;
191 double width = clip.ContainsKey(
"width") ? Convert.ToDouble(clip[
"width"]) :
Puppeteer.GetScreenWidthInt();
192 double height = clip.ContainsKey(
"height") ? Convert.ToDouble(clip[
"height"]) :
Puppeteer.GetScreenHeightInt();
193 double scale = clip.ContainsKey(
"scale") ? Convert.ToDouble(clip[
"scale"]) : 1.0;
195 if (width > 0 && height > 0 && x >= 0 && y >= 0)
197 parameters =
new Dictionary<string, object>
199 {
"format", format },
201 "clip",
new Dictionary<string, object>
206 {
"height", height },
214 GPAL.
PublishSimpleEvent(GPALEventType.WARNING, $
"Invalid clip parameters: x=[{x}], y=[{y}], width=[{width}], height=[{height}]. Using viewport.",
this, GPALObjectType.PuppeteerClient);
218 JObject retData = await c.SendCommand(DevToolsMethods.PageCaptureScreenshot, parameters, s).ConfigureAwait(
false);
219 string base64 = retData[
"data"]?.ToString();
223 [RESTHelper.Endpoints[ApiEndpoint.CastDesktop]] = async (c, p, s) =>
225 string sinkName = p.ContainsKey(
"sinkName") ? p[
"sinkName"]?.ToString() :
null;
226 await c.CastDesktop(sinkName, s).ConfigureAwait(
false);
229 [RESTHelper.Endpoints[ApiEndpoint.CastTab]] = async (c, p, s) =>
231 string sinkName = p.ContainsKey(
"sinkName") ? p[
"sinkName"]?.ToString() :
null;
232 await c.CastTab(sinkName, s).ConfigureAwait(
false);
235 [RESTHelper.Endpoints[ApiEndpoint.CheckNetworkIdle]] = async (c, p, s) =>
237 string sessionToken = Guid.NewGuid().ToString();
238 return await c.CheckNetworkIdle(s, _maxConnections, _timeoutMs, _pruneMs, sessionToken).ConfigureAwait(
false);
240 [RESTHelper.Endpoints[ApiEndpoint.ClearReferrer]] = async (c, p, s) =>
242 return await c.SendCommand(DevToolsMethods.NetworkSetExtraHTTPHeaders,
new Dictionary<string, object> { {
"headers", new Dictionary<string, object> { {
"Referer",
"" } } } }, s).ConfigureAwait(
false);
244 [RESTHelper.Endpoints[ApiEndpoint.CloseTab]] = async (c, p, s) =>
246 string targetId =
null;
247 if (p.ContainsKey(
"tabId"))
249 int tabId =
int.Parse(p[
"tabId"]?.ToString());
250 var queueArray = c.CurrentSessions.ToArray();
251 if (tabId >= 0 && tabId < queueArray.Length)
253 targetId = queueArray[tabId].Key;
258 targetId = c.GetCurrentTargetId();
261 if (targetId !=
null)
263 await c.CloseTab(targetId, s).ConfigureAwait(
false);
268 [RESTHelper.Endpoints[ApiEndpoint.CloseWindow]] = async (c, p, s) =>
270 string targetId =
null;
271 string windowId = p.ContainsKey(
"windowId") ? p[
"windowId"]?.ToString() :
null;
272 string url = p.ContainsKey(
"url") ? p[
"url"]?.ToString() :
null;
274 if (!
string.IsNullOrEmpty(windowId))
278 else if (!
string.IsNullOrEmpty(url))
280 targetId = await c.GetTargetWindowIdByUrl(url).ConfigureAwait(
false);
281 if (targetId !=
null)
284 int windowIndex = c.GetCurrentWindowIndex(targetId);
285 if (windowIndex >= 0)
287 c.SetActiveWindowIndex(windowIndex);
293 targetId = c.GetCurrentWindowTargetId();
296 if (!
string.IsNullOrEmpty(targetId))
298 await c.CloseWindow(targetId, s).ConfigureAwait(
false);
302 GPAL.
PublishSimpleEvent(GPALEventType.ERROR, $
"Unable to find window for targetId [{targetId}] or URL [{url}]", c, GPALObjectType.Puppeteer);
305 [RESTHelper.Endpoints[ApiEndpoint.DeleteStorage]] = async (c, p, s) =>
307 var storageType = p.ContainsKey(
"storageType") ? p[
"storageType"]?.ToString() :
"";
308 var domain = p.ContainsKey(
"domain") ? p[
"domain"]?.ToString() :
"";
309 var path = p.ContainsKey(
"path") ? p[
"path"]?.ToString() :
"";
310 var key = p.ContainsKey(
"key") ? p[
"key"]?.ToString() :
"";
311 var storeName = p.ContainsKey(
"storeName") ? p[
"storeName"]?.ToString() :
"";
313 return await c.DeleteStorage(storageType, s, domain, storeName, path, key).ConfigureAwait(
false);
315 [RESTHelper.Endpoints[ApiEndpoint.DragAndDrop]] = async (c, p, s) =>
317 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
318 List<GPALElement> elems = p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] : await _puppeteerCommunicator.EvaluateSelector(parm).ConfigureAwait(
false);
319 var deltaX = p.ContainsKey(
"deltaX") ? Convert.ToInt32(p[
"deltaX"]) : 0;
320 var deltaY = p.ContainsKey(
"deltaY") ? Convert.ToInt32(p[
"deltaY"]) : 0;
321 var offsetX = p.ContainsKey(
"offsetX") ? Convert.ToInt32(p[
"offsetX"]) : 0;
322 var offsetY = p.ContainsKey(
"offsetY") ? Convert.ToInt32(p[
"offsetY"]) : 0;
323 List<dynamic> responses =
new List<dynamic>();
327 await c.ScrollIntoView(elem, s).ConfigureAwait(
false);
328 await c.DragAndDrop(elem, s, responses, deltaX, deltaY, offsetX, offsetY).ConfigureAwait(
false);
331 return (responses, elems);
333 [RESTHelper.Endpoints[ApiEndpoint.Evaluate]] = async (c, p, s) =>
335 var xpath = p.ContainsKey(
"xpath") ? p[
"xpath"]?.ToString() :
"";
336 xpath = xpath.Replace(
"'",
"\\'");
337 List<GPALElement> elems = await _puppeteerCommunicator.EvaluateSelector(xpath, s).ConfigureAwait(
false);
345 [RESTHelper.Endpoints[ApiEndpoint.EvaluateAll]] = async (c, p, s) =>
347 var xpath = p.ContainsKey(
"xpath") ? p[
"xpath"]?.ToString() :
"";
349 xpath = xpath.Replace(
"'",
"\\'");
350 return await _puppeteerCommunicator.EvaluateSelector(xpath, s).ConfigureAwait(
false);
413 [RESTHelper.Endpoints[ApiEndpoint.Fetch]] = async (c, p, s) =>
415 return await c.Fetch(
416 p.ContainsKey(
"url") ? p[
"url"]?.ToString() :
null,
417 p.ContainsKey(
"method") ? p[
"method"]?.ToString() :
null,
418 p.ContainsKey(
"body") ? p[
"body"]?.ToString() :
null,
419 p.ContainsKey(
"contentType") ? p[
"contentType"]?.ToString() :
null,
420 p.ContainsKey(
"headers") ? p[
"headers"] as
string[] :
null,
421 p.ContainsKey(
"bytes") &&
true == Convert.ToBoolean(p[
"bytes"]),
422 s).ConfigureAwait(
false);
424 [RESTHelper.Endpoints[ApiEndpoint.ExecuteJavaScript]] = async (c, p, s) =>
426 var expression = p.ContainsKey(
"expression") ? p[
"expression"]?.ToString() : p[
"script"]?.ToString();
427 return await c.SendCommand<
object>(DevToolsMethods.RuntimeEvaluate,
new
430 returnByValue =
true,
432 }, s).ConfigureAwait(
false);
434 [RESTHelper.Endpoints[ApiEndpoint.FillInAppend]] = async (c, p, s) =>
436 List<dynamic> responses =
new List<dynamic>();
438 List<GPALElement> elems = (List<GPALElement>)(p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] :
null);
439 var text = p.ContainsKey(
"text") ? p[
"text"]?.ToString() :
"";
440 var typingDelay = p.ContainsKey(
"typingDelay") ? Convert.ToInt32(p[
"typingDelay"]) : 0;
442 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
444 if (
null == elems &&
null != parm)
445 elems = await _puppeteerCommunicator.EvaluateSelector(parm).ConfigureAwait(
false);
449 await c.ScrollIntoView(element, s).ConfigureAwait(
false);
453 await c.FocusElement(element.ElementHandle, s).ConfigureAwait(
false);
454 responses.Add(await c.FillIn(element.ElementHandle, element.
Value + text, typingDelay, s).ConfigureAwait(
false));
487 return new { responses, elems };
489 [RESTHelper.Endpoints[ApiEndpoint.FillInInsert]] = async (c, p, s) =>
491 List<dynamic> responses =
new List<dynamic>();
492 List<GPALElement> elems = (List<GPALElement>)(p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] :
null);
493 var text = p.ContainsKey(
"text") ? p[
"text"]?.ToString() :
"";
494 var typingDelay = p.ContainsKey(
"typingDelay") ? Convert.ToInt32(p[
"typingDelay"]) : 0;
496 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
498 if (
null == elems &&
null != parm)
499 elems = await _puppeteerCommunicator.EvaluateSelector(parm).ConfigureAwait(
false);
503 await c.ScrollIntoView(element, s).ConfigureAwait(
false);
507 await c.FocusElement(element.ElementHandle, s).ConfigureAwait(
false);
508 responses.Add(await c.FillIn(element.ElementHandle, text + element.
Value, typingDelay, s).ConfigureAwait(
false));
541 return new { responses, elems };
543 [RESTHelper.Endpoints[ApiEndpoint.FillInOverwrite]] = async (c, p, s) =>
545 List<dynamic> responses =
new List<dynamic>();
546 List<GPALElement> elems = (List<GPALElement>)(p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] :
null);
547 var text = p.ContainsKey(
"text") ? p[
"text"]?.ToString() :
"";
548 var typingDelay = p.ContainsKey(
"typingDelay") ? Convert.ToInt32(p[
"typingDelay"]) : 0;
550 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
552 if (
null == elems &&
null != parm)
553 elems = await _puppeteerCommunicator.EvaluateSelector(parm).ConfigureAwait(
false);
557 await c.ScrollIntoView(element, s).ConfigureAwait(
false);
561 await c.FocusElement(element.ElementHandle, s).ConfigureAwait(
false);
562 responses.Add(await c.FillIn(element.ElementHandle, text, typingDelay, s).ConfigureAwait(
false));
564 return new { responses, elems };
566 [RESTHelper.Endpoints[ApiEndpoint.FireChangeEvent]] = async (c, p, s) =>
568 dynamic selector = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
569 return await c.SendCommand<
object>(DevToolsMethods.RuntimeEvaluate,
new
571 expression = $
"document.querySelector('{selector.Replace("'", "\\'")}').dispatchEvent(new Event('change'))",
573 }, s).ConfigureAwait(
false);
575 [RESTHelper.Endpoints[ApiEndpoint.Focus]] = async (c, p, s) =>
577 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
579 List<GPALElement> elems = p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] : await _puppeteerCommunicator.EvaluateSelector(parm).ConfigureAwait(
false);
583 var requestNodeResult = await c.SendCommand<
object>(DevToolsMethods.DOMRequestNode,
new { objectId = elem.ElementHandle }, s).ConfigureAwait(
false);
585 if (requestNodeResult?.nodeId !=
null)
587 return await c.SendCommand<
object>(DevToolsMethods.DOMFocus,
new { nodeId = (int)requestNodeResult.nodeId }, s).ConfigureAwait(
false);
599 [RESTHelper.Endpoints[ApiEndpoint.Forward]] = async (c, p, s) =>
601 return await c.Forward(s).ConfigureAwait(
false);
603 [RESTHelper.Endpoints[ApiEndpoint.FullScreen]] = async (c, p, s) =>
605 var windowId = await c.GetCurrentWindow(s).ConfigureAwait(
false);
606 return await c.SendCommand(DevToolsMethods.BrowserSetWindowBounds,
new
609 bounds = new { windowState =
"fullscreen" }
610 }, s).ConfigureAwait(
false);
612 [RESTHelper.Endpoints[ApiEndpoint.GetAttribute]] = async (c, p, s) =>
614 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
615 var attribute = p.ContainsKey(
"attribute") ? p[
"attribute"]?.ToString() :
"";
616 List<GPALElement> elems = p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] : await _puppeteerCommunicator.EvaluateSelector(parm).ConfigureAwait(
false);
623 [RESTHelper.Endpoints[ApiEndpoint.GetBoundingClientRect]] = async (c, p, s) =>
625 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
627 return await c.GetBoundingClientRect(Int32.Parse(parm)).ConfigureAwait(
false);
629 [RESTHelper.Endpoints[ApiEndpoint.GetContentAndCss]] = async (c, p, s) =>
631 var selector = p.ContainsKey(
"elementId") ? p[
"elementId"]?.ToString() :
"";
632 return await c.SendCommand<
object>(DevToolsMethods.RuntimeEvaluate,
new
634 expression = $
"(() => {{ const el = document.querySelector('{selector.Replace("'", "\\'")}'); return {{ text: el.textContent, css: window.getComputedStyle(el).cssText }}; }})()",
636 }, s).ConfigureAwait(
false);
638 [RESTHelper.Endpoints[ApiEndpoint.GetCssAttributes]] = async (c, p, s) =>
640 string backendNodeId = p.ContainsKey(
"elementId") ? p[
"elementId"]?.ToString() :
null;
642 return await c.GetCssAttributes(Int32.Parse(backendNodeId), s).ConfigureAwait(
false);
644 [RESTHelper.Endpoints[ApiEndpoint.GetCurrentUrl]] = async (c, p, s) =>
646 return await c.GetCurrentUrl(s).ConfigureAwait(
false);
648 [RESTHelper.Endpoints[ApiEndpoint.GetCurrentWindow]] = async (c, p, s) =>
650 return await c.GetCurrentWindow(s).ConfigureAwait(
false);
652 [RESTHelper.Endpoints[ApiEndpoint.GetDomAttributes]] = async (c, p, s) =>
654 string backendNodeId = p.ContainsKey(
"elementId") ? p[
"elementId"]?.ToString() :
null;
656 return await c.GetDomAttributes(Int32.Parse(backendNodeId), s).ConfigureAwait(
false);
658 [RESTHelper.Endpoints[ApiEndpoint.GetDomProperties]] = async (c, p, s) =>
660 string backendNodeId = p.ContainsKey(
"elementId") ? p[
"elementId"]?.ToString() :
null;
662 return await c.GetDomProperties(Int32.Parse(backendNodeId), s).ConfigureAwait(
false);
664 [RESTHelper.Endpoints[ApiEndpoint.GetElementAttributeHash]] = async (c, p, s) =>
666 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
667 var text = p.ContainsKey(
"text") ? p[
"text"]?.ToString() :
"";
668 var attribute = p.ContainsKey(
"attribute") ? p[
"attribute"]?.ToString() :
"";
669 List<GPALElement> elems = p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] : await _puppeteerCommunicator.EvaluateSelector(parm).ConfigureAwait(
false);
676 [RESTHelper.Endpoints[ApiEndpoint.GetPageSource]] = async (c, p, s) =>
678 return await c.GetPageSource(s).ConfigureAwait(
false);
680 [RESTHelper.Endpoints[ApiEndpoint.GetParentNode]] = async (c, p, s) =>
682 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
683 List<GPALElement> elems = p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] : await _puppeteerCommunicator.EvaluateSelector(parm).ConfigureAwait(
false);
689 if (!
string.IsNullOrEmpty(elem.ElementHandle))
692 var parentResult = await c.SendCommand<
object>(
693 DevToolsMethods.RuntimeCallFunctionOn,
696 objectId = elem.ElementHandle,
697 functionDeclaration =
"function() { return this.parentElement; }",
698 returnByValue =
false,
701 s).ConfigureAwait(
false);
703 if (parentResult?.result?.objectId !=
null)
705 string parentObjectId = parentResult.result.objectId;
708 var parentElems = await c.EvaluateSelector(parentObjectId).ConfigureAwait(
false);
710 return parentElems[0];
716 [RESTHelper.Endpoints[ApiEndpoint.GetReadyStatus]] = async (c, p, s) =>
718 dynamic sessionToken = p.ContainsKey(
"sessionToken") ? p[
"sessionToken"] :
null;
719 return await c.GetReadyStatus(s, sessionToken).ConfigureAwait(
false);
721 [RESTHelper.Endpoints[ApiEndpoint.GetShadowRoot]] = async (c, p, s) =>
724 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
725 List<GPALElement> elems = p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] : await _puppeteerCommunicator.EvaluateSelector(parm).ConfigureAwait(
false);
731 [RESTHelper.Endpoints[ApiEndpoint.GetStorage]] = async (c, p, s) =>
733 var storageType = p.ContainsKey(
"storageType") ? p[
"storageType"]?.ToString() :
null;
734 var domain = p.ContainsKey(
"domain") ? p[
"domain"]?.ToString() :
null;
735 var path = p.ContainsKey(
"path") ? p[
"path"]?.ToString() :
null;
736 var key = p.ContainsKey(
"key") ? p[
"key"]?.ToString() :
null;
737 var storeName = p.ContainsKey(
"storeName") ? p[
"storeName"]?.ToString() :
null;
739 return await c.GetStorage(storageType, s, domain, storeName, path, key).ConfigureAwait(
false);
741 [RESTHelper.Endpoints[ApiEndpoint.GetLanguages]] = async (c, p, s) =>
743 var languages = await c.SendCommand<
object>(DevToolsMethods.RuntimeEvaluate,
new
745 expression =
"navigator.languages.join(',')",
747 }, s).ConfigureAwait(
false);
748 return (
string)languages.result.value;
750 [RESTHelper.Endpoints[ApiEndpoint.GetUserAgent]] = async (c, p, s) =>
752 var result = await c.SendCommand<
object>(DevToolsMethods.RuntimeEvaluate,
new
754 expression =
"navigator.userAgent",
756 }, s).ConfigureAwait(
false);
757 return (
string)result.result.value;
759 [RESTHelper.Endpoints[ApiEndpoint.GoTo]] = async (c, p, s) =>
769 var url = p.ContainsKey(
"url") ? p[
"url"]?.ToString() :
"about:blank";
770 return await c.GoTo(url, s).ConfigureAwait(
false);
772 [RESTHelper.Endpoints[ApiEndpoint.GoToTab]] = async (c, p, s) =>
774 string tabId = p.ContainsKey(
"tabId") ? p[
"tabId"]?.ToString() :
null;
775 string url = p.ContainsKey(
"url") ? p[
"url"]?.ToString() :
null;
776 int? index = p.TryGetValue(
"index", out
object value) &&
int.TryParse(value?.ToString(), out
int parsed) ? (
int?)parsed :
null;
778 object tabIdOrUrlOrIndex = tabId ?? url ?? (object)index;
779 if (tabIdOrUrlOrIndex ==
null)
781 GPAL.
PublishSimpleEvent(GPALEventType.WARNING,
"No valid input provided for GoToTab (tabId, url, or index required)", c, GPALObjectType.PuppeteerCommunicator);
785 string targetId = await c.GoToTab(tabIdOrUrlOrIndex, s).ConfigureAwait(
false);
786 if (targetId ==
null)
788 GPAL.
PublishSimpleEvent(GPALEventType.WARNING, $
"Failed to switch to tab for input [{tabIdOrUrlOrIndex}]", c, GPALObjectType.PuppeteerCommunicator);
792 return new { targetId };
794 [RESTHelper.Endpoints[ApiEndpoint.GoToWindow]] = async (c, p, s) =>
796 var tabIdOrUrl = p.ContainsKey(
"tabId") ? (object)Convert.ToInt32(p[
"tabId"])
797 : (object)(p.ContainsKey(
"url") ? p[
"url"]?.ToString() :
null);
799 if (tabIdOrUrl ==
null)
802 var targetId = await c.GoToWindow(tabIdOrUrl, s).ConfigureAwait(
false);
804 if (!
string.IsNullOrEmpty(targetId))
806 _currentTargetId = targetId;
807 return new { targetId };
810 return new { targetId };
812 [RESTHelper.Endpoints[ApiEndpoint.HideElement]] = async (c, p, s) =>
814 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
815 p.ContainsKey(
"css") ? p[
"css"] :
816 p.ContainsKey(
"xpath") ? p[
"xpath"] :
null;
817 List<GPALElement> elems = p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] as List<GPALElement> :
818 await c.EvaluateSelector(parm).ConfigureAwait(
false);
819 if (elems ==
null || !elems.Any())
821 GPAL.
PublishSimpleEvent(GPALEventType.WARNING,
"No elements resolved for HideElement", c, GPALObjectType.Puppeteer);
825 List<dynamic> responses =
new List<dynamic>();
828 responses.Add(await c.HideElement(elem.ElementBackendNodeId, s).ConfigureAwait(
false));
831 return (responses, elems);
833 [RESTHelper.Endpoints[ApiEndpoint.Hover]] = async (c, p, s) =>
835 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
836 List<GPALElement> elems = p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] : await _puppeteerCommunicator.EvaluateSelector(parm).ConfigureAwait(
false);
837 List<dynamic> responses =
new List<dynamic>();
839 await c.MoveTo(elems, s, responses).ConfigureAwait(
false);
841 return (responses, elems);
843 [RESTHelper.Endpoints[ApiEndpoint.ClickPoint]] = async (c, p, s) =>
845 var x = p.ContainsKey(
"x") ? Convert.ToInt32(p[
"x"]) : 0;
846 var y = p.ContainsKey(
"y") ? Convert.ToInt32(p[
"y"]) : 0;
847 var clickType = p.ContainsKey(
"clickType") ? (ClickType)Convert.ToInt32(p[
"clickType"]) : ClickType.LeftClick;
848 var modifiers = p.ContainsKey(
"modifiers") ? Convert.ToInt32(p[
"modifiers"]) : 0;
849 List<dynamic> responses =
new List<dynamic>();
851 await c.ClickElement(x, y, s, responses, clickType, modifiers).ConfigureAwait(
false);
854 [RESTHelper.Endpoints[ApiEndpoint.MoveToPoint]] = async (c, p, s) =>
856 var x = p.ContainsKey(
"x") ? Convert.ToInt32(p[
"x"]) : 0;
857 var y = p.ContainsKey(
"y") ? Convert.ToInt32(p[
"y"]) : 0;
859 await c.MoveTo(x, y, s).ConfigureAwait(
false);
862 [RESTHelper.Endpoints[ApiEndpoint.InjectScript]] = async (c, p, s) =>
864 var script = p.ContainsKey(
"script") ? p[
"script"]?.ToString() :
"";
865 await c.InjectScript(script, s).ConfigureAwait(
false);
868 [RESTHelper.Endpoints[ApiEndpoint.ClearInjectedScripts]] = async (c, p, s) =>
870 await c.ClearInjectedScripts(s).ConfigureAwait(
false);
873 [RESTHelper.Endpoints[ApiEndpoint.SwitchToDefaultContent]] = async (c, p, s) =>
876 await c.SwitchToDefaultContent(s).ConfigureAwait(
false);
879 [RESTHelper.Endpoints[ApiEndpoint.SwitchToShadowRoot]] = (c, p, s) =>
884 [RESTHelper.Endpoints[ApiEndpoint.IsClickable]] = async (c, p, s) =>
888 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
889 List<GPALElement> elems = p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] : await _puppeteerCommunicator.EvaluateSelector(parm).ConfigureAwait(
false);
890 List<bool> isClickables =
new List<bool>();
896 return isClickables.All(isClickAble =>
true == isClickAble);
898 [RESTHelper.Endpoints[ApiEndpoint.IsDisplayed]] = async (c, p, s) =>
902 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
903 List<GPALElement> elems = p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] : await _puppeteerCommunicator.EvaluateSelector(parm).ConfigureAwait(
false);
905 bool isDisplayed =
true;
912 [RESTHelper.Endpoints[ApiEndpoint.IsEnabled]] = async (c, p, s) =>
916 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
917 List<GPALElement> elems = p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] : await _puppeteerCommunicator.EvaluateSelector(parm).ConfigureAwait(
false);
919 bool isDisabled =
false;
926 [RESTHelper.Endpoints[ApiEndpoint.IsEndOfPage]] = async (c, p, s) =>
928 return await c.IsEndOfPage(s).ConfigureAwait(
false);
930 [RESTHelper.Endpoints[ApiEndpoint.IsVisibleInViewport]] = async (c, p, s) =>
934 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
935 List<GPALElement> elems = (List<GPALElement>)(p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] :
null);
938 return await c.IsVisibleInViewport(elems, s).ConfigureAwait(
false);
940 return await c.IsVisibleInViewport(parm, s).ConfigureAwait(
false);
942 [RESTHelper.Endpoints[ApiEndpoint.LeftClick]] = async (c, p, s) =>
944 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
945 List<GPALElement> elems = p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] : await _puppeteerCommunicator.EvaluateSelector(parm).ConfigureAwait(
false);
946 int modifiers = p.ContainsKey(
"modifiers") ? Convert.ToInt32(p[
"modifiers"]) : 0;
947 List<dynamic> responses =
new List<dynamic>();
951 await c.ScrollIntoView(element, s).ConfigureAwait(
false);
952 await c.ClickElement(element, s, responses, ClickType.LeftClick, modifiers).ConfigureAwait(
false);
955 return (responses, elems);
957 [RESTHelper.Endpoints[ApiEndpoint.LeftDoubleClick]] = async (c, p, s) =>
959 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
960 List<GPALElement> elems = p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] : await _puppeteerCommunicator.EvaluateSelector(parm).ConfigureAwait(
false);
961 int modifiers = p.ContainsKey(
"modifiers") ? Convert.ToInt32(p[
"modifiers"]) : 0;
962 List<dynamic> responses =
new List<dynamic>();
966 await c.ScrollIntoView(element, s).ConfigureAwait(
false);
967 await c.ClickElement(element, s, responses, ClickType.LeftDoubleClick, modifiers).ConfigureAwait(
false);
970 return (responses, elems);
972 [RESTHelper.Endpoints[ApiEndpoint.LeftClickAndDownload]] = async (c, p, s) =>
974 string downloadPath = p.ContainsKey(
"downloadPath") ? p[
"downloadPath"]?.ToString() :
"";
975 dynamic elementId = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
976 int modifiers = p.ContainsKey(
"modifiers") ? Convert.ToInt32(p[
"modifiers"]) : 0;
978 List<GPALElement> elems = p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] : await _puppeteerCommunicator.EvaluateSelector(elementId).ConfigureAwait(
false);
979 List<dynamic> responses =
new List<dynamic>();
983 await c.LeftClickAndDownload(elems, downloadPath, modifiers, s, responses).ConfigureAwait(
false);
988 return (responses, elems);
990 [RESTHelper.Endpoints[ApiEndpoint.Upload]] = async (c, p, s) =>
992 GPALFile uploadPaths = p.ContainsKey(
"uploadPaths") ? (
GPALFile)p[
"uploadPaths"] :
null;
993 string uploadPath = p.ContainsKey(
"uploadPath") ? p[
"uploadPath"]?.ToString() :
"";
994 dynamic elementId = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
995 int modifiers = p.ContainsKey(
"modifiers") ? Convert.ToInt32(p[
"modifiers"]) : 0;
997 List<GPALElement> elems = p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] : await _puppeteerCommunicator.EvaluateSelector(elementId).ConfigureAwait(
false);
998 List<dynamic> responses =
new List<dynamic>();
1002 if (0 < uploadPaths?.Count)
1003 await c.LeftClickAndUpload(elems, uploadPaths, modifiers, s, responses).ConfigureAwait(
false);
1005 await c.LeftClickAndUpload(elems, uploadPath, modifiers, s, responses).ConfigureAwait(
false);
1010 return (responses, elems);
1012 [RESTHelper.Endpoints[ApiEndpoint.LeftDoubleClick]] = async (c, p, s) =>
1014 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
1015 List<GPALElement> elems = p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] : await _puppeteerCommunicator.EvaluateSelector(parm).ConfigureAwait(
false);
1016 int modifiers = p.ContainsKey(
"modifiers") ? Convert.ToInt32(p[
"modifiers"]) : 0;
1018 List<dynamic> responses =
new List<dynamic>();
1022 await c.ScrollIntoView(element, s).ConfigureAwait(
false);
1023 await c.ClickElement(element, s, responses, ClickType.LeftDoubleClick, modifiers).ConfigureAwait(
false);
1025 return (responses, elems);
1027 [RESTHelper.Endpoints[ApiEndpoint.MiddleClick]] = async (c, p, s) =>
1029 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
1030 List<GPALElement> elems = p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] : await _puppeteerCommunicator.EvaluateSelector(parm).ConfigureAwait(
false);
1031 int modifiers = p.ContainsKey(
"modifiers") ? Convert.ToInt32(p[
"modifiers"]) : 0;
1032 List<dynamic> responses =
new List<dynamic>();
1036 await c.ScrollIntoView(element, s).ConfigureAwait(
false);
1037 await c.ClickElement(element, s, responses, ClickType.
MiddleClick, modifiers).ConfigureAwait(
false);
1040 return (responses, elems);
1042 [RESTHelper.Endpoints[ApiEndpoint.Maximize]] = async (c, p, s) =>
1044 return await c.Maximize(s).ConfigureAwait(
false);
1046 [RESTHelper.Endpoints[ApiEndpoint.Minimize]] = async (c, p, s) =>
1048 return await c.Minimize(s).ConfigureAwait(
false);
1050 [RESTHelper.Endpoints[ApiEndpoint.MoveTo]] = async (c, p, s) =>
1052 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
1053 List<GPALElement> elems = p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] : await _puppeteerCommunicator.EvaluateSelector(parm).ConfigureAwait(
false);
1054 List<dynamic> responses =
new List<dynamic>();
1056 return await c.MoveTo(elems, s, responses).ConfigureAwait(
false);
1058 [RESTHelper.Endpoints[ApiEndpoint.NewTab]] = async (c, p, s) =>
1060 var url = p.ContainsKey(
"url") ? p[
"url"]?.ToString() :
"https://google.com";
1061 var targetId = await c.NewTab(url, s).ConfigureAwait(
false);
1063 if (!
string.IsNullOrEmpty(targetId))
1064 _currentTargetId = targetId;
1067 "NewTab: Failed to open a new tab",
1068 this, GPALObjectType.Puppeteer);
1070 return _currentTargetId;
1072 [RESTHelper.Endpoints[ApiEndpoint.NextTab]] = async (c, p, s) =>
1074 var tmp = _currentTargetId;
1076 _currentTargetId = await c.NextTab(_currentTargetId).ConfigureAwait(
false);
1078 return _currentTargetId;
1080 [RESTHelper.Endpoints[ApiEndpoint.NextWindow]] = async (c, p, s) =>
1082 _currentTargetId = await c.NextWindow(_currentTargetId).ConfigureAwait(
false);
1084 return _currentTargetId;
1086 [RESTHelper.Endpoints[ApiEndpoint.Normal]] = async (c, p, s) =>
1088 return await c.Normal(s).ConfigureAwait(
false);
1090 [RESTHelper.Endpoints[ApiEndpoint.OpenWindow]] = async (c, p, s) =>
1092 var url = p.ContainsKey(
"url") ? p[
"url"]?.ToString() :
"about:blank";
1094 _currentTargetId = await c.OpenWindow(url, s).ConfigureAwait(
false);
1096 return _currentTargetId;
1098 [RESTHelper.Endpoints[ApiEndpoint.OverrideReferrer]] = async (c, p, s) =>
1100 var referrer = p.ContainsKey(
"referrer") ? p[
"referrer"]?.ToString() :
"";
1101 return await c.SendCommand<
object>(DevToolsMethods.NetworkSetExtraHTTPHeaders,
new
1103 headers =
new Dictionary<string, object> { {
"Referer", referrer } }
1104 }, s).ConfigureAwait(
false);
1106 [RESTHelper.Endpoints[ApiEndpoint.SetUserAgent]] = async (c, p, s) =>
1108 var userAgent = p.ContainsKey(
"userAgent") ? p[
"userAgent"]?.ToString() :
"";
1109 return await c.SetUserAgent(userAgent, s).ConfigureAwait(
false);
1111 [RESTHelper.Endpoints[ApiEndpoint.PageDown]] = async (c, p, s) =>
1113 int pagesToScroll = p.ContainsKey(
"pagesToScroll") ? Convert.ToInt32(p[
"pagesToScroll"]) : 1;
1114 return await c.ScrollPageAsync(
"down", pagesToScroll, s).ConfigureAwait(
false);
1116 [RESTHelper.Endpoints[ApiEndpoint.PageEnd]] = async (c, p, s) =>
1118 return await c.ScrollToPositionAsync(
"end", s).ConfigureAwait(
false);
1120 [RESTHelper.Endpoints[ApiEndpoint.PageTop]] = async (c, p, s) =>
1122 return await c.ScrollToPositionAsync(
"top", s).ConfigureAwait(
false);
1124 [RESTHelper.Endpoints[ApiEndpoint.PageUp]] = async (c, p, s) =>
1126 int pagesToScroll = p.ContainsKey(
"pagesToScroll") ? Convert.ToInt32(p[
"pagesToScroll"]) : 1;
1127 return await c.ScrollPageAsync(
"up", pagesToScroll, s).ConfigureAwait(
false);
1129 [RESTHelper.Endpoints[ApiEndpoint.PressModifierKey]] = async (c, p, s) =>
1131 var modifier = p.ContainsKey(
"modifier") ? Convert.ToInt32(p[
"modifier"]) : 0;
1132 return await c.SendCommand<
object>(DevToolsMethods.InputDispatchKeyEvent,
new
1135 modifiers = modifier
1136 }, s).ConfigureAwait(
false);
1138 [RESTHelper.Endpoints[ApiEndpoint.PreviousTab]] = async (c, p, s) =>
1140 _currentTargetId = await c.PreviousTab(_currentTargetId).ConfigureAwait(
false);
1142 return _currentTargetId;
1144 [RESTHelper.Endpoints[ApiEndpoint.PreviousWindow]] = async (c, p, s) =>
1146 _currentTargetId = await c.PreviousWindow(_currentTargetId).ConfigureAwait(
false);
1148 return _currentTargetId;
1150 [RESTHelper.Endpoints[ApiEndpoint.QuerySelector]] = async (c, p, s) =>
1152 var selector = p.ContainsKey(
"css") ? p[
"css"]?.ToString() :
"";
1153 List<GPALElement> elems = await _puppeteerCommunicator.EvaluateSelector(selector, s).ConfigureAwait(
false);
1155 if (0 < elems.Count)
1162 [RESTHelper.Endpoints[ApiEndpoint.QuerySelectors]] = async (c, p, s) =>
1164 var selector = p.ContainsKey(
"css") ? p[
"css"]?.ToString() :
"";
1165 return await _puppeteerCommunicator.EvaluateSelector(selector, s).ConfigureAwait(
false);
1167 [RESTHelper.Endpoints[ApiEndpoint.Refresh]] = async (c, p, s) =>
1169 return await c.SendCommand(DevToolsMethods.PageReload,
new { }, s).ConfigureAwait(
false);
1171 [RESTHelper.Endpoints[ApiEndpoint.ReleaseModifierKey]] = async (c, p, s) =>
1173 var modifier = p.ContainsKey(
"modifier") ? Convert.ToInt32(p[
"modifier"]) : 0;
1174 return await c.SendCommand<
object>(DevToolsMethods.InputDispatchKeyEvent,
new
1177 modifiers = modifier
1178 }, s).ConfigureAwait(
false);
1180 [RESTHelper.Endpoints[ApiEndpoint.Restore]] = async (c, p, s) =>
1182 return await c.Restore(s).ConfigureAwait(
false);
1184 [RESTHelper.Endpoints[ApiEndpoint.RightClick]] = async (c, p, s) =>
1186 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
1187 List<dynamic> responses =
new List<dynamic>();
1188 List<GPALElement> elems = p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] : await _puppeteerCommunicator.EvaluateSelector(parm).ConfigureAwait(
false);
1192 await c.ScrollIntoView(element, s).ConfigureAwait(
false);
1193 await c.ClickElement(element, s, responses, ClickType.RightClick).ConfigureAwait(
false);
1197 [RESTHelper.Endpoints[ApiEndpoint.RightClickAndDownload]] = async (c, p, s) =>
1199 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
1200 List<GPALElement> elems = p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] : await _puppeteerCommunicator.EvaluateSelector(parm).ConfigureAwait(
false);
1201 var filename = p.ContainsKey(
"downloadPath") ? p[
"downloadPath"]?.ToString() :
"";
1203 await c.SendCommand<
object>(DevToolsMethods.PageSetDownloadBehavior,
new { behavior =
"allow", downloadPath = filename }, s).ConfigureAwait(
false);
1207 var random =
new Random();
1211 var x = (float)element.
BoundingRect.
X + (
float)element.BoundingRect.Width * margin + (float)random.NextDouble() * clickAreaWidth;
1212 var y = (float)element.
BoundingRect.
Y + (
float)element.BoundingRect.Height * margin + (float)random.NextDouble() * clickAreaHeight;
1214 if (
true ==
"A".Equals(element.
TagName))
1216 x = (float)element.
BoundingRect.
X + (
float)element.BoundingRect.Width / 2;
1217 y = (float)element.
BoundingRect.
Y + (
float)element.BoundingRect.Height / 2;
1221 var pressResult = await c.SendCommand<
object>(DevToolsMethods.InputDispatchMouseEvent,
new
1223 type =
"mousePressed",
1226 x = x +
new Random().Next(-2, 3),
1227 y = y +
new Random().Next(-2, 3),
1229 timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
1230 }, s).ConfigureAwait(
false);
1233 await Task.Delay(
new Random().Next(50, 150)).ConfigureAwait(
false);
1236 var releaseResult = await c.SendCommand<
object>(DevToolsMethods.InputDispatchMouseEvent,
new
1238 type =
"mouseReleased",
1241 x = x +
new Random().Next(-2, 3),
1242 y = x +
new Random().Next(-2, 3),
1244 timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
1245 }, s).ConfigureAwait(
false);
1248 await c.SendCommand<
object>(DevToolsMethods.PageSetDownloadBehavior,
new
1251 }, s).ConfigureAwait(
false);
1254 [RESTHelper.Endpoints[ApiEndpoint.ScrollElement]] = async (c, p, s) =>
1256 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
1257 List<GPALElement> elems = p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] : await _puppeteerCommunicator.EvaluateSelector(parm).ConfigureAwait(
false);
1258 bool isObjectId = System.Text.RegularExpressions.Regex.IsMatch(parm,
@"^-?\d+\.\d+\.\d+$");
1259 var hPixels = p.ContainsKey(
"hPixels") ? Convert.ToInt32(p[
"hPixels"]) : 0;
1260 var vPixels = p.ContainsKey(
"vPixels") ? Convert.ToInt32(p[
"vPixels"]) : 0;
1261 List<dynamic> responses =
new List<dynamic>();
1266 (function(selector, hPixels, vPixels) {{
1267 function evaluateSelector(selector) {{
1269 let type = 'unknown';
1271 nodes = Array.from(document.querySelectorAll(selector));
1272 if (nodes.length > 0) return nodes;
1276 const result = document.evaluate(selector, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
1277 nodes = Array.from({{ length: result.snapshotLength }}, (_, i) => result.snapshotItem(i));
1278 if (nodes.length > 0) return nodes;
1284 const elements = evaluateSelector(selector);
1285 elements.forEach(el => {{
1286 if (el.scrollBy) el.scrollBy(hPixels, vPixels);
1288 return elements.length; // optional: return number of elements scrolled
1289 }})('{(true == isObjectId ? (elem.Css ?? elem.Xpath) : parm).Replace("'", "\\'")}', {hPixels}, {vPixels})";
1291 responses.Add(await c.SendCommand<
object>(DevToolsMethods.RuntimeEvaluate,
new
1293 expression = jsFunc,
1294 returnByValue = true
1295 }, s).ConfigureAwait(
false));
1297 return (responses, elems);
1299 [RESTHelper.Endpoints[ApiEndpoint.ScrollIntoView]] = async (c, p, s) =>
1301 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
1302 List<GPALElement> elems = p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] : await _puppeteerCommunicator.EvaluateSelector(parm).ConfigureAwait(
false);
1303 List<dynamic> responses =
new List<dynamic>();
1307 responses.Add(await c.ScrollIntoView(elem, s).ConfigureAwait(
false));
1309 return (responses, elems);
1311 [RESTHelper.Endpoints[ApiEndpoint.ScrollWindow]] = async (c, p, s) =>
1313 var hPixels = p.ContainsKey(
"hPixels") ? Convert.ToInt32(p[
"hPixels"]) : 0;
1314 var vPixels = p.ContainsKey(
"vPixels") ? Convert.ToInt32(p[
"vPixels"]) : 0;
1315 return await c.ScrollWindowByPixelsAsync(hPixels, vPixels, s).ConfigureAwait(
false);
1322 [RESTHelper.Endpoints[ApiEndpoint.SelectClick]] = async (c, p, s) =>
1325 dynamic elementHandle = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
1326 string selectValue = p.ContainsKey(
"selectValue") ? p[
"selectValue"]?.ToString() :
null;
1327 int? selectIndex = p.ContainsKey(
"selectIndex") &&
int.TryParse(p[
"selectIndex"]?.ToString(), out
int idx) ? idx : (
int?)
null;
1328 bool result =
false;
1330 if (selectIndex.HasValue)
1332 result = await c.SelectByIndex(elementHandle, selectIndex.Value, s).ConfigureAwait(
false);
1336 string safeValue = selectValue.Replace(
"'",
"\\'");
1337 result = await c.SelectByValue(elementHandle, safeValue, s).ConfigureAwait(
false);
1342 [RESTHelper.Endpoints[ApiEndpoint.SendKey]] = async (c, p, s) =>
1344 var key = p.ContainsKey(
"key") ? p[
"key"]?.ToString() :
"Unidentified";
1345 var code = p.ContainsKey(
"code") ? p[
"code"]?.ToString() :
"Unidentified";
1346 var vk = p.ContainsKey(
"vk") ? Convert.ToInt32(p[
"vk"]) : 0;
1348 return await c.SendKey(key, code, vk).ConfigureAwait(
false);
1351 [RESTHelper.Endpoints[ApiEndpoint.SendString]] = async (c, p, s) =>
1353 var text = p.ContainsKey(
"text") ? p[
"text"]?.ToString() :
"";
1354 var typingDelay = p.ContainsKey(
"typingDelay") ? Convert.ToInt32(p[
"typingDelay"]) : 0;
1355 await c.SendString(text, typingDelay, s).ConfigureAwait(
false);
1358 [RESTHelper.Endpoints[ApiEndpoint.SetAttribute]] = async (c, p, s) =>
1360 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
1361 var value = p.ContainsKey(
"value") ? p[
"value"]?.ToString() : p[
"text"]?.ToString();
1362 var attribute = p.ContainsKey(
"attribute") ? p[
"attribute"] :
"";
1363 bool isObjectId = System.Text.RegularExpressions.Regex.IsMatch(parm,
@"^-?\d+\.\d+\.\d+$");
1364 List<GPALElement> elems = p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] : await _puppeteerCommunicator.EvaluateSelector(parm).ConfigureAwait(
false);
1365 List<dynamic> responses =
new List<dynamic>();
1370 (function(selector, attribute, value) {{
1371 function evaluateSelector(selector) {{
1373 let type = 'unknown';
1375 nodes = Array.from(document.querySelectorAll(selector));
1376 if (nodes.length > 0) return nodes;
1380 const result = document.evaluate(selector, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
1381 nodes = Array.from({{ length: result.snapshotLength }}, (_, i) => result.snapshotItem(i));
1382 if (nodes.length > 0) return nodes;
1388 const elements = evaluateSelector(selector);
1389 elements.forEach(el => {{
1390 el.setAttribute(attribute, value);
1392 return elements.length; // optional: return number of elements scrolled
1393 }})('{(true == isObjectId ? (elem.Css ?? elem.Xpath) : parm).Replace("'", "\\'")}', {attribute}, {value})";
1395 responses.Add(await c.SendCommand<
object>(DevToolsMethods.RuntimeEvaluate,
new
1397 expression = jsFunc,
1398 returnByValue = true
1399 }, s).ConfigureAwait(
false));
1400 elem.
Attributes[attribute.ToString()] = value;
1402 return (responses, elems);
1404 [RESTHelper.Endpoints[ApiEndpoint.SetDownloadFilename]] = async (c, p, s) =>
1406 var filename = p.ContainsKey(
"filename") ? p[
"filename"]?.ToString() :
"";
1407 return await c.SendCommand<
object>(DevToolsMethods.PageSetDownloadBehavior,
new
1410 downloadPath = filename
1411 }, s).ConfigureAwait(
false);
1413 [RESTHelper.Endpoints[ApiEndpoint.SetRange]] = async (c, p, s) =>
1415 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
1416 List<GPALElement> elems = p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] : await _puppeteerCommunicator.EvaluateSelector(parm).ConfigureAwait(
false);
1417 string rangeValue = (string)(p.ContainsKey(
"rangeValue") ? p[
"rangeValue"] :
"0xdeadbeef");
1418 List<dynamic> responses =
new List<dynamic>();
1420 if (
"0xdeadbeef" != rangeValue)
1422 responses.Add(await c.SetRange(elem.
Css, rangeValue, s).ConfigureAwait(
false));
1426 [RESTHelper.Endpoints[ApiEndpoint.SetValueFromElement]] = async (c, p, s) =>
1428 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
1429 List<GPALElement> elems = p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] : await _puppeteerCommunicator.EvaluateSelector(parm).ConfigureAwait(
false);
1430 string destSelector = p.ContainsKey(
"destSelector") ? p[
"destSelector"]?.ToString() :
null;
1431 List<dynamic> responses =
new List<dynamic>();
1433 if (
false ==
string.IsNullOrEmpty(destSelector))
1435 responses.Add(await c.SetValueFromElement(elem.
Css, destSelector, s).ConfigureAwait(
false));
1439 [RESTHelper.Endpoints[ApiEndpoint.SetStorage]] = async (c, p, s) =>
1441 var storageType = p.ContainsKey(
"storageType") ? p[
"storageType"]?.ToString() :
"";
1442 var domain = p.ContainsKey(
"domain") ? p[
"domain"]?.ToString() :
"";
1443 var storeName = p.ContainsKey(
"storeName") ? p[
"storeName"]?.ToString() :
null;
1444 var path = p.ContainsKey(
"path") ? p[
"path"]?.ToString() :
"";
1445 var key = p.ContainsKey(
"key") ? p[
"key"]?.ToString() :
"";
1446 var data = p.ContainsKey(
"data") ? p[
"data"]?.ToString() :
"";
1448 return await c.SetStorage(storageType, s, domain, key, data, storeName, path).ConfigureAwait(
false);
1450 [RESTHelper.Endpoints[ApiEndpoint.StealthOverrideReferrer]] = async (c, p, s) =>
1452 return await c.SendCommand<
object>(DevToolsMethods.NetworkSetExtraHTTPHeaders,
new
1454 headers =
new Dictionary<string, object> { {
"Referer",
"https://www.google.com" } }
1455 }, s).ConfigureAwait(
false);
1457 [RESTHelper.Endpoints[ApiEndpoint.StopCasting]] = async (c, p, s) =>
1459 return await c.StopCasting(s).ConfigureAwait(
false);
1461 [RESTHelper.Endpoints[ApiEndpoint.SubmitForm]] = async (c, p, s) =>
1463 dynamic parm = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
1464 List<GPALElement> elems = p.ContainsKey(
"gpalElements") ? p[
"gpalElements"] : await _puppeteerCommunicator.EvaluateSelector(parm).ConfigureAwait(
false);
1465 List<dynamic> responses =
new List<dynamic>();
1469 responses.Add(await c.SubmitForm(elem.ElementHandle, s).ConfigureAwait(
false));
1505 return (responses, elems);
1507 [RESTHelper.Endpoints[ApiEndpoint.SwitchToDefaultContent]] = async (c, p, s) =>
1510 await c.SwitchToDefaultContent(s).ConfigureAwait(
false);
1513 [RESTHelper.Endpoints[ApiEndpoint.SwitchToElement]] = async (c, p, s) =>
1515 dynamic selector = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
1516 await c.SwitchToElement(selector).ConfigureAwait(
false);
1519 [RESTHelper.Endpoints[ApiEndpoint.SwitchToFrame]] = async (c, p, s) =>
1521 dynamic selector = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
1522 await c.SwitchToFrame(selector).ConfigureAwait(
false);
1525 [RESTHelper.Endpoints[ApiEndpoint.SwitchToShadowRoot]] = async (c, p, s) =>
1527 dynamic selector = p.ContainsKey(
"elementId") ? p[
"elementId"] :
null;
1528 await c.SwitchToShadowDom(selector).ConfigureAwait(
false);
1531 [RESTHelper.Endpoints[ApiEndpoint.TopBrowser]] = async (c, p, s) =>
1533 await c.TopBrowser().ConfigureAwait(
false);
1536 [RESTHelper.Endpoints[ApiEndpoint.WindowInnerHeight]] = async (c, p, s) =>
1538 var result = await c.SendCommand<
object>(DevToolsMethods.RuntimeEvaluate,
new
1540 expression =
"window.innerHeight",
1541 returnByValue =
true
1543 }, c.GetCurrentSessionId()).ConfigureAwait(
false);
1544 return (
int)result.result.value;
1546 [RESTHelper.Endpoints[ApiEndpoint.WindowInnerWidth]] = async (c, p, s) =>
1548 var result = await c.SendCommand<
object>(DevToolsMethods.RuntimeEvaluate,
new
1550 expression =
"window.innerWidth",
1551 returnByValue =
true
1553 }, c.GetCurrentSessionId()).ConfigureAwait(
false);
1554 return (
int)result.result.value;
1556 [RESTHelper.Endpoints[ApiEndpoint.WindowOuterHeight]] = async (c, p, s) =>
1558 var result = await c.SendCommand<
object>(DevToolsMethods.RuntimeEvaluate,
new
1560 expression =
"window.outerHeight",
1561 returnByValue =
true
1563 }, c.GetCurrentSessionId()).ConfigureAwait(
false);
1564 return (
int)result.result.value;
1566 [RESTHelper.Endpoints[ApiEndpoint.WindowOuterWidth]] = async (c, p, s) =>
1568 var result = await c.SendCommand<
object>(DevToolsMethods.RuntimeEvaluate,
new
1570 expression =
"window.outerWidth",
1571 returnByValue =
true
1573 }, c.GetCurrentSessionId()).ConfigureAwait(
false);
1574 return (
int)result.result.value;
1576 [RESTHelper.Endpoints[ApiEndpoint.WindowPageOffsetX]] = async (c, p, s) =>
1578 var result = await c.SendCommand<
object>(DevToolsMethods.RuntimeEvaluate,
new
1580 expression =
"window.pageXOffset",
1581 returnByValue =
true
1582 }, s).ConfigureAwait(
false);
1583 return (
int)result.result.value;
1585 [RESTHelper.Endpoints[ApiEndpoint.WindowPageOffsetY]] = async (c, p, s) =>
1587 var result = await c.SendCommand<
object>(DevToolsMethods.RuntimeEvaluate,
new
1589 expression =
"window.pageYOffset",
1590 returnByValue =
true
1591 }, s).ConfigureAwait(
false);
1592 return (
int)result.result.value;
1594 [RESTHelper.Endpoints[ApiEndpoint.WindowScreenLeft]] = async (c, p, s) =>
1596 var result = await c.SendCommand<
object>(DevToolsMethods.RuntimeEvaluate,
new
1598 expression =
"window.screenLeft",
1599 returnByValue =
true
1601 }, c.GetCurrentSessionId()).ConfigureAwait(
false);
1602 return (
int)result.result.value;
1604 [RESTHelper.Endpoints[ApiEndpoint.WindowScreenTop]] = async (c, p, s) =>
1606 var result = await c.SendCommand<
object>(DevToolsMethods.RuntimeEvaluate,
new
1608 expression =
"window.screenTop",
1609 returnByValue =
true
1611 }, c.GetCurrentSessionId()).ConfigureAwait(
false);
1612 return (
int)result.result.value;
1621 public IPuppeteerClient ToGPALObject()
1661 _puppeteerCommunicator = communicator;
1673 _endpoint = endpoint;
1674 _customEndpoint =
true;
1686 _apiEndpoint = endpoint;
1687 _endpoint = RESTHelper.Endpoints.TryGetValue(endpoint, out var ep) ? ep :
"";
1698 _nextResultName = name;
1702 public IAllowPuppeteerEndpointDetails WithSaveFile(
GPALFile file)
1715 SetParameter(
"sessionToken", sessionToken);
1737 SetParameter(
"url", url);
1748 SetParameter(
"imageFormat", imageFormat.ToString());
1759 var url = GetResultFromIndex(resultIndex)?.ToString() ??
"";
1770 var url = GetResultFromName(name)?.ToString() ??
"";
1781 SetParameter(
"tabId", tabId);
1792 var tabId = GetResultFromIndex(resultIndex) is
int i ? i : 0;
1803 var tabId = GetResultFromName(name) is
int i ? i : 0;
1814 SetParameter(
"windowId", windowId);
1825 var windowId = GetResultFromIndex(resultIndex) is
int i ? i : 0;
1836 var windowId = GetResultFromName(name) is
int i ? i : 0;
1847 SetParameter(
"domain", domain);
1857 SetParameter(
"path", path);
1867 SetParameter(
"key", key);
1877 SetParameter(
"storeName", storeName);
1887 SetParameter(
"data", data);
1897 SetParameter(
"crossOrigin", trueOrFalse);
1907 SetParameter(
"key", key);
1918 var key = GetResultFromIndex(resultIndex)?.ToString() ??
"";
1929 var key = GetResultFromName(name)?.ToString() ??
"";
1940 SetParameter(
"css", css);
1951 var css = GetResultFromIndex(resultIndex)?.ToString() ??
"";
1962 var css = GetResultFromName(name)?.ToString() ??
"";
1973 SetParameter(
"gpalElements", gpalElements);
1984 var elementId = GetResultFromIndex(resultIndex)?.ToString() ??
"";
1995 var elementId = GetResultFromName(name)?.ToString() ??
"";
2005 _currentIteration = iteration > 0 ? iteration : 1;
2015 SetParameter(
"xpath", xpath);
2026 var xpath = GetResultFromIndex(resultIndex)?.ToString() ??
"";
2037 var xpath = GetResultFromName(name)?.ToString() ??
"";
2048 SetParameter(
"pixels", pixels);
2059 var pixels = GetResultFromIndex(resultIndex) is
int i ? i : 0;
2070 var pixels = GetResultFromName(name) is
int i ? i : 0;
2081 SetParameter(
"referrer", referrer);
2092 var referrer = GetResultFromIndex(resultIndex)?.ToString() ??
"";
2103 var referrer = GetResultFromName(name)?.ToString() ??
"";
2115 SetParameter(
"text", text);
2126 var text = GetResultFromIndex(resultIndex)?.ToString() ??
"";
2137 var text = GetResultFromName(name)?.ToString() ??
"";
2151 SetParameter(
"downloadPath", file.
Filename);
2159 private List<GPALElement> GetElements(
string selector)
2161 return _puppeteerCommunicator.EvaluateSelector(selector).Result;
2170 bool isObjectId = System.Text.RegularExpressions.Regex.IsMatch(selector,
@"^-?\d+\.\d+\.\d+$");
2174 SetParameter(
"elementId", selector);
2191 var elementId = GetResultFromIndex(resultIndex)?.ToString() ??
"";
2202 var elementId = GetResultFromName(name)?.ToString() ??
"";
2213 _hPixels = GetResultFromIndex(resultIndex) is
int i ? i : 0;
2214 SetParameter(
"hPixels", _hPixels);
2225 _hPixels = GetResultFromName(name) is
int i ? i : 0;
2226 SetParameter(
"hPixels", _hPixels);
2235 public IAllowPuppeteerParametersOrExecution WithVPixelsFromResult(
int resultIndex)
2237 _vPixels = GetResultFromIndex(resultIndex) is
int i ? i : 0;
2238 SetParameter(
"vPixels", _vPixels);
2249 _vPixels = GetResultFromName(name) is
int i ? i : 0;
2250 SetParameter(
"vPixels", _vPixels);
2258 public string Execute()
2260 return Task.Run(async () => await
ExecuteAsync().ConfigureAwait(
false)).GetAwaiter().GetResult();
2263 public T Execute<T>()
2267 Task<T> task = ExecuteAsync<T>();
2272 return Task.Run(async () => await task.ConfigureAwait(
false)).GetAwaiter().GetResult();
2280 catch (Exception ex)
2282 GPAL.PublishSimpleEvent(GPALEventType.EXCEPTION, $
"Failed to execute synchronously for type [{typeof(T).Name}].",
this, GPALObjectType.PuppeteerClient, ex);
2291 public IAllowPuppeteerParametersOrExecution AndThen()
2297 public IAllowPuppeteerParametersOrExecution AndThen<T>()
2307 public async Task<string> ExecuteAsync()
2309 var result = await ExecuteInternalAsync().ConfigureAwait(
false);
2310 return result?.ToString() ??
"";
2313 public async Task<T> ExecuteAsync<T>()
2315 dynamic result = await ExecuteInternalAsync().ConfigureAwait(
false);
2319 GPAL.PublishSimpleEvent(GPALEventType.EXCEPTION,
"ExecuteInternalAsync returned null.",
this, GPALObjectType.PuppeteerClient,
null);
2323 if (typeof(T) == typeof(JObject))
2325 if (result is JObject)
2327 return (T)(object)result;
2329 GPAL.PublishSimpleEvent(GPALEventType.EXCEPTION, $
"Expected JObject but got [{result.GetType().Name}].",
this, GPALObjectType.PuppeteerClient,
null);
2340 if (result is JToken)
2342 return JsonConvert.DeserializeObject<T>(result.ToString());
2352 if (result is JObject jObject)
2354 JToken resultToken = jObject[
"result"];
2355 if (resultToken ==
null)
2357 GPAL.
PublishSimpleEvent(GPALEventType.EXCEPTION,
"Result object is missing 'result' property.",
this, GPALObjectType.PuppeteerClient,
null);
2361 JToken valueToken = resultToken[
"value"];
2362 if (valueToken !=
null)
2365 if (typeof(T) == typeof(
string) && valueToken.Type == JTokenType.String)
2367 return (T)(object)valueToken.ToString();
2372 return JsonConvert.DeserializeObject<T>(valueToken.ToString());
2374 catch (Exception ex)
2376 GPAL.
PublishSimpleEvent(GPALEventType.EXCEPTION, $
"Failed to deserialize result.value [{valueToken.ToString()}] to type [{typeof(T).Name}].",
this, GPALObjectType.PuppeteerClient, ex);
2383 return JsonConvert.DeserializeObject<T>(resultToken.ToString());
2385 catch (Exception ex)
2387 GPAL.
PublishSimpleEvent(GPALEventType.EXCEPTION, $
"Failed to deserialize result [{resultToken.ToString()}] to type [{typeof(T).Name}].",
this, GPALObjectType.PuppeteerClient, ex);
2392 GPAL.
PublishSimpleEvent(GPALEventType.EXCEPTION, $
"Unsupported result type [{result.GetType().Name}] for type [{typeof(T).Name}].",
this, GPALObjectType.PuppeteerClient,
null);
2403 foreach (var entry
in _executionResults)
2405 results[entry.Name] = entry.Result;
2418 _headers[name] = value;
2429 SetParameter(
"parameters", parameters);
2440 SetParameter(
"parameters", parameters);
2451 SetParameter(
"parameters", GetResultFromIndex(resultIndex));
2462 SetParameter(
"parameters", GetResultFromName(name));
2473 _contentEncoding = encoding;
2484 _workflows.Add(w => workflow((
RESTClient)(
object)
this));
2495 _whileLoopTimeoutMs = timeoutMs;
2506 _whileLoopMaxIterations = maxIterations;
2517 _loopCondition = condition;
2518 _loopType =
"While";
2529 _loopCondition = condition;
2530 _loopType =
"Until";
2541 _timeoutMs = timeoutMs;
2563 _maxConnections = maxConnections;
2585 SetParameter(
"hPixels", hPixels);
2596 SetParameter(
"vPixels", vPixels);
2607 SetParameter(
"deltaX", deltaX);
2618 SetParameter(
"deltaY", deltaY);
2629 SetParameter(
"offsetX", offsetX);
2640 SetParameter(
"offsetY", offsetY);
2651 _attribute = attribute;
2652 SetParameter(
"attribute", attribute);
2664 SetParameter(
"value", value);
2675 SetParameter(
"destElementId", destElementId);
2686 SetParameter(
"sinkName", sinkName);
2707 WithImageFormat(imageFormat);
2719 WithEndpoint(ApiEndpoint.CastDesktop).WithDeviceName(deviceNameOrId);
2730 WithEndpoint(ApiEndpoint.CastTab).WithDeviceName(deviceNameOrId);
2742 if (url !=
null)
WithUrl(url.Url);
2766 if (url !=
null)
WithUrl(url.Url);
2790 SetParameter(
"storageType", storageType.ToString());
2803 SetParameter(
"script", script);
2816 SetParameter(
"url", url);
2827 SetParameter(
"method", method);
2838 SetParameter(
"body", body);
2849 SetParameter(
"contentType", contentType);
2860 SetParameter(
"headers", headers);
2872 SetParameter(
"bytes", asBytes);
2888 else if (elementOrelementId is List<GPALElement> elements)
2893 SetParameter(
"typingDelay", delayMs);
2909 else if (elementOrelementId is List<GPALElement> elements)
2910 WithElements(elements);
2912 WithElementId(elementOrelementId);
2914 SetParameter(
"typingDelay", delayMs);
2926 WithEndpoint(ApiEndpoint.FillInOverwrite);
2929 WithElements(
new List<GPALElement>() { element });
2930 else if (elementOrelementId is List<GPALElement> elements)
2935 SetParameter(
"typingDelay", delayMs);
2968 if (
false ==
string.IsNullOrEmpty(sessionToken))
3025 WithEndpoint(ApiEndpoint.GetStorage);
3026 SetParameter(
"storageType", storageType.ToString());
3037 WithEndpoint(ApiEndpoint.GetLanguages);
3047 WithEndpoint(ApiEndpoint.GetUserAgent);
3058 url.
ForUrl(
MagicHelper.GetFullUrl(url?.
Url, _puppeteerCommunicator.Browser, out _puppeteerCommunicator.Browser._areRobotsAllowed));
3060 if (
false == _puppeteerCommunicator.Browser.AreRobotsAllowed &&
true == _puppeteerCommunicator.Browser.BrowserSettings.ObeyRobotsTxt)
3062 GPAL.
PublishSimpleEvent(GPALEventType.ERROR, $
"[{url?.Url}] not allowed to robots and your honoring robots.txt. Not going to URL. Workflow will fail.",
this, GPALObjectType.PuppeteerClient);
3065 WithEndpoint(ApiEndpoint.GoTo);
3158 WithEndpoint(ApiEndpoint.Maximize);
3191 WithEndpoint(ApiEndpoint.NewTab);
3193 url?.
ForUrl(
MagicHelper.GetFullUrl(url?.Url, _puppeteerCommunicator.Browser, out _puppeteerCommunicator.Browser._areRobotsAllowed));
3195 if (
false == _puppeteerCommunicator.Browser.AreRobotsAllowed &&
true == _puppeteerCommunicator.Browser.BrowserSettings.ObeyRobotsTxt)
3197 GPAL.
PublishSimpleEvent(GPALEventType.ERROR, $
"[{url.Url}] not allowed to robots and your honoring robots.txt. Not going to URL. Workflow will fail.",
this, GPALObjectType.PuppeteerClient);
3198 url.
ForUrl(
"https://google.com");
3209 public IAllowPuppeteerExecution NextTab()
3211 WithEndpoint(ApiEndpoint.NextTab);
3221 WithEndpoint(ApiEndpoint.NextWindow);
3244 url.
ForUrl(
MagicHelper.GetFullUrl(url?.
Url, _puppeteerCommunicator.Browser, out _puppeteerCommunicator.Browser._areRobotsAllowed));
3246 if (
false == _puppeteerCommunicator.Browser.AreRobotsAllowed &&
true == _puppeteerCommunicator.Browser.BrowserSettings.ObeyRobotsTxt)
3248 GPAL.
PublishSimpleEvent(GPALEventType.ERROR, $
"[{url?.Url}] not allowed to robots and your honoring robots.txt. Not going to URL. Workflow will fail.",
this, GPALObjectType.PuppeteerClient);
3249 url.
ForUrl(
"https://google.com");
3276 SetParameter(
"userAgent", userAgent);
3288 SetParameter(
"pagesToScroll", pagesToScroll);
3298 WithEndpoint(ApiEndpoint.PageEnd);
3308 WithEndpoint(ApiEndpoint.PageTop);
3320 SetParameter(
"pagesToScroll", pagesToScroll);
3350 WithEndpoint(ApiEndpoint.Refresh);
3387 if (modifierKeys.HasFlag(ModifierKeys.Alt))
3389 if (modifierKeys.HasFlag(ModifierKeys.Control))
3391 if (modifierKeys.HasFlag(ModifierKeys.Windows))
3393 if (modifierKeys.HasFlag(ModifierKeys.Shift))
3402 public string GetModifiersString(
int bitmask)
3404 var modifiers =
new List<string>();
3406 if ((bitmask & 1) != 0)
3407 modifiers.Add(
"Alt");
3408 if ((bitmask & 2) != 0)
3409 modifiers.Add(
"Control");
3410 if ((bitmask & 4) != 0)
3411 modifiers.Add(
"Windows");
3412 if ((bitmask & 8) != 0)
3413 modifiers.Add(
"Shift");
3415 return modifiers.Count > 0 ?
string.Join(
"+", modifiers) :
"None";
3458 WithEndpoint(ApiEndpoint.ScrollWindowByHorizontal);
3459 SetParameter(
"hPixels", pixels);
3471 SetParameter(
"vPixels", pixels);
3485 SetParameter(
"typingDelay", delayMs);
3499 SetParameter(
"key", key);
3500 SetParameter(
"code", code);
3501 SetParameter(
"vk", (
int)vkcode);
3512 WithEndpoint(ApiEndpoint.OverrideReferrer).WithReferrer(
"https://www.google.com");
3592 SetParameter(
"script", script);
3616 SetParameter(
"downloadPath", downloadPath);
3792 WithEndpoint(ApiEndpoint.IsEndOfPage);
3804 SetParameter(
"gpalElements",
new List<GPALElement>() { (
GPALElement)element });
3815 WithEndpoint(ApiEndpoint.IsVisibleInViewport);
3816 WithElementId(backendNodeId);
3827 if (elementOrelementId is System.Drawing.Point point)
3828 return WithClickPoint(point, ClickType.LeftClick);
3834 else if (elementOrelementId is List<GPALElement> elements)
3849 if (elementOrelementId is System.Drawing.Point point)
3850 return WithClickPoint(point, ClickType.MiddleClick);
3856 else if (elementOrelementId is List<GPALElement> elements)
3871 if (elementOrelementId is System.Drawing.Point point)
3872 return WithClickPoint(point, ClickType.LeftDoubleClick);
3878 else if (elementOrelementId is List<GPALElement> elements)
3879 WithElements(elements);
3881 WithElementId(elementOrelementId);
3893 if (elementOrelementId is System.Drawing.Point point)
3894 return WithClickPoint(point, ClickType.RightClick);
3900 else if (elementOrelementId is List<GPALElement> elements)
3901 WithElements(elements);
3903 WithElementId(elementOrelementId);
3913 public IAllowPuppeteerSelectOptions SelectClick(
string elementHandle)
3927 SetParameter(
"selectValue", value);
3937 SetParameter(
"selectIndex", index);
3951 else if (elementOrelementId is List<GPALElement> elements)
3995 WithEndpoint(ApiEndpoint.WindowOuterWidth);
4005 WithEndpoint(ApiEndpoint.WindowPageOffsetX);
4013 public IAllowPuppeteerExecution WindowPageOffsetY()
4015 WithEndpoint(ApiEndpoint.WindowPageOffsetY);
4023 public IAllowPuppeteerExecution WindowScreenLeft()
4035 WithEndpoint(ApiEndpoint.WindowScreenTop);
4061 SetParameter(
"x", point.X);
4062 SetParameter(
"y", point.Y);
4063 SetParameter(
"clickType", (
int)clickType);
4076 SetParameter(
"x", point.X);
4077 SetParameter(
"y", point.Y);
4184 WithEndpoint(ApiEndpoint.SetRange);
4196 SetParameter(
"rangeValue", rangeValue.ToString());
4206 WithEndpoint(ApiEndpoint.ScrollElement);
4219 WithEndpoint(ApiEndpoint.ScrollElement);
4233 public IAllowPuppeteerExecution SetValueFrom(
string destSelector)
4235 WithEndpoint(ApiEndpoint.SetValueFromElement);
4236 SetParameter(
"destSelector", destSelector);
4244 public IAllowPuppeteerExecution TopBrowser()
4246 WithEndpoint(ApiEndpoint.TopBrowser);
4267 private object GetResultFromIndex(
int index)
4269 if (index < 0 || index >= _executionResults.Count)
return null;
4270 return _executionResults[index].Result;
4278 private object GetResultFromName(
string name)
4280 return _executionResults.FirstOrDefault(entry => entry.Name == name && entry.Iteration == _currentIteration && entry.TargetId == _currentTargetId).Result;
4288 private void SetParameter(
string key,
object value)
4290 if (_parameters ==
null) _parameters =
new Dictionary<string, object>();
4291 ((Dictionary<string, object>)_parameters)[key] = value;
4299 public IAllowPuppeteerStorageOptions SetStorage(WebsiteStorageType storageType)
4301 WithEndpoint(ApiEndpoint.SetStorage);
4302 SetParameter(
"storageType", storageType.ToString());
4309 private void Reset()
4313 _customEndpoint =
false;
4314 _nextResultName =
null;
4315 _timeoutMs = 30_000;
4317 _maxConnections = 0;
4323 _currentIteration = 1;
4324 _loopCondition =
null;
4326 _whileLoopTimeoutMs = 0;
4327 _whileLoopMaxIterations = 0;
4334 private async Task<object> ExecuteInternalAsync()
4336 if (
true == _puppeteerCommunicator._windowSessionsQueue.IsEmpty)
4338 GPAL.PublishSimpleEvent(GPALEventType.WARNING, $
"No browser windows open. Cannot call endpoint [{_endpoint}]",
null, GPALObjectType.None);
4342 if (
string.IsNullOrEmpty(_endpoint))
4344 GPAL.PublishSimpleEvent(GPALEventType.WARNING, $
"[{_name}] No endpoint specified",
null, GPALObjectType.None);
4348 var parameters = _parameters as IDictionary<string, object> ??
4349 (_parameters?.GetType().GetProperties().ToDictionary(p => p.Name, p => p.GetValue(_parameters)) ??
new Dictionary<string, object>());
4351 if (!_customEndpoint && !restClient.ValidateParameters(_apiEndpoint, parameters))
4356 object result =
null;
4358 if (_loopCondition !=
null && !
string.IsNullOrEmpty(_loopType))
4360 int maxIterations = _whileLoopMaxIterations > 0 ? _whileLoopMaxIterations : 1000;
4362 var startTime = DateTime.UtcNow;
4363 int timeoutMs = _whileLoopTimeoutMs > 0 ? _whileLoopTimeoutMs :
int.MaxValue;
4365 if (_loopType ==
"While")
4368 while (_loopCondition() && iteration < maxIterations && (DateTime.UtcNow - startTime).TotalMilliseconds < timeoutMs)
4371 result = await ExecuteEndpoint(_endpoint, parameters).ConfigureAwait(
false);
4374 await Task.Delay(100).ConfigureAwait(
false);
4377 else if (_loopType ==
"Until")
4382 result = await ExecuteEndpoint(_endpoint, parameters).ConfigureAwait(
false);
4385 await Task.Delay(100).ConfigureAwait(
false);
4386 }
while (!_loopCondition() && iteration < maxIterations && (DateTime.UtcNow - startTime).TotalMilliseconds < timeoutMs);
4389 if (iteration >= maxIterations)
4391 GPAL.PublishSimpleEvent(GPALEventType.WARNING, $
"[{_name}] Loop exceeded max iterations [{maxIterations}]",
null, GPALObjectType.None);
4393 else if ((DateTime.UtcNow - startTime).TotalMilliseconds >= timeoutMs)
4395 GPAL.PublishSimpleEvent(GPALEventType.WARNING, $
"[{_name}] Loop exceeded timeout [{timeoutMs}ms]",
null, GPALObjectType.None);
4401 result = await ExecuteEndpoint(_endpoint, parameters).ConfigureAwait(
false);
4404 if (!
string.IsNullOrEmpty(_saveFile))
4406 SaveResponseToFile(result?.ToString(), _saveFile);
4409 if (!
string.IsNullOrEmpty(_nextResultName))
4411 _executionResults.Add((_nextResultName, result, _executionResults.Where(r => r.Name == _nextResultName && r.TargetId == _currentTargetId).Select(r => r.Iteration).DefaultIfEmpty(0).Max() + 1, _currentTargetId));
4412 _workflowStates.Add((_endpoint, _parameters, _nextResultName));
4416 string valueStr = (result as JObject)?[
"result"]?[
"value"]?.Value<string>();
4417 if (!
string.IsNullOrEmpty(valueStr))
4422 statusCode = (int) JObject.Parse(valueStr)[
"status"]?.Value<
int>();
4428 _puppeteerCommunicator.ServerResponseCode = statusCode;
4429 if (statusCode < 200 || statusCode >= 300)
4430 GPAL.PublishSimpleEvent(GPALEventType.WARNING, $
"[{_name}] Endpoint [{_endpoint}] returned HTTP [{statusCode}]",
null, GPALObjectType.None);
4435 _loopCondition =
null;
4437 _whileLoopTimeoutMs = 0;
4438 _whileLoopMaxIterations = 0;
4449 private async Task<object> ExecuteEndpoint(
string endpoint, IDictionary<string, object> parameters)
4451 if (endpointMap.TryGetValue(endpoint, out var handler))
4454 var sessionId = _puppeteerCommunicator.GetEffectiveSessionId();
4455 if (sessionId ==
null)
4457 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"No active session for execution. Using null.",
this, GPALObjectType.Puppeteer);
4460 return await handler(_puppeteerCommunicator, parameters, sessionId).ConfigureAwait(
false);