Wanderhalleylee commited on
Commit
af4de95
·
verified ·
1 Parent(s): d361e52

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +135 -38
app.py CHANGED
@@ -505,11 +505,24 @@ async def interact_screenshot(request: SessionRequest, auth=Depends(verify_token
505
  driver = session['driver']
506
 
507
  try:
 
 
 
 
 
 
 
 
 
 
 
 
508
  screenshot = driver.get_screenshot_as_png()
509
  screenshot_b64 = base64.b64encode(screenshot).decode('utf-8')
510
 
511
  return {
512
  "screenshot": screenshot_b64,
 
513
  "url": driver.current_url,
514
  "title": driver.title
515
  }
@@ -517,35 +530,87 @@ async def interact_screenshot(request: SessionRequest, auth=Depends(verify_token
517
  logger.error(f"[INTERACT-SCREENSHOT] Erro: {e}")
518
  raise HTTPException(status_code=500, detail=str(e))
519
 
 
520
  @app.post("/interact/click")
521
  async def interact_click(request: InteractClickRequest, auth=Depends(verify_token)):
522
- """Clica em coordenada específica na página"""
523
  session = session_manager.get_session(request.session_id)
524
  driver = session['driver']
525
 
526
  try:
527
- actions = ActionChains(driver)
528
- actions.move_by_offset(0, 0).perform()
529
- actions.reset_actions()
530
-
531
- # Usar JavaScript para clicar na posição exata
532
- driver.execute_script(f"""
533
- var element = document.elementFromPoint({request.x}, {request.y});
534
- if (element) {{
535
- element.click();
536
- element.focus();
537
- }}
538
- """)
539
 
540
- time.sleep(0.5)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
541
 
542
  screenshot = driver.get_screenshot_as_png()
543
  screenshot_b64 = base64.b64encode(screenshot).decode('utf-8')
544
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
545
  return {
546
  "status": "clicked",
547
  "x": request.x,
548
  "y": request.y,
 
549
  "screenshot": screenshot_b64,
550
  "url": driver.current_url,
551
  "title": driver.title
@@ -554,22 +619,47 @@ async def interact_click(request: InteractClickRequest, auth=Depends(verify_toke
554
  logger.error(f"[INTERACT-CLICK] Erro: {e}")
555
  raise HTTPException(status_code=500, detail=str(e))
556
 
 
557
  @app.post("/interact/type")
558
  async def interact_type(request: InteractTypeRequest, auth=Depends(verify_token)):
559
- """Digita texto no elemento focado"""
560
  session = session_manager.get_session(request.session_id)
561
  driver = session['driver']
562
 
563
  try:
564
- # Digitar no elemento ativo
565
- driver.execute_script("""
566
- var el = document.activeElement;
567
- if (el && (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA' || el.isContentEditable)) {
568
- el.value = el.value + arguments[0];
569
- el.dispatchEvent(new Event('input', { bubbles: true }));
570
- el.dispatchEvent(new Event('change', { bubbles: true }));
571
- }
572
- """, request.text)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
573
 
574
  time.sleep(0.3)
575
 
@@ -578,7 +668,7 @@ async def interact_type(request: InteractTypeRequest, auth=Depends(verify_token)
578
 
579
  return {
580
  "status": "typed",
581
- "text": request.text,
582
  "screenshot": screenshot_b64,
583
  "url": driver.current_url,
584
  "title": driver.title
@@ -587,9 +677,10 @@ async def interact_type(request: InteractTypeRequest, auth=Depends(verify_token)
587
  logger.error(f"[INTERACT-TYPE] Erro: {e}")
588
  raise HTTPException(status_code=500, detail=str(e))
589
 
 
590
  @app.post("/interact/key")
591
  async def interact_key(request: InteractKeyRequest, auth=Depends(verify_token)):
592
- """Pressiona tecla especial"""
593
  session = session_manager.get_session(request.session_id)
594
  driver = session['driver']
595
 
@@ -612,9 +703,10 @@ async def interact_key(request: InteractKeyRequest, auth=Depends(verify_token)):
612
  raise HTTPException(status_code=400, detail=f"Tecla não suportada: {request.key}")
613
 
614
  actions = ActionChains(driver)
615
- actions.send_keys(key).perform()
 
616
 
617
- time.sleep(0.5)
618
 
619
  screenshot = driver.get_screenshot_as_png()
620
  screenshot_b64 = base64.b64encode(screenshot).decode('utf-8')
@@ -632,6 +724,7 @@ async def interact_key(request: InteractKeyRequest, auth=Depends(verify_token)):
632
  logger.error(f"[INTERACT-KEY] Erro: {e}")
633
  raise HTTPException(status_code=500, detail=str(e))
634
 
 
635
  @app.post("/interact/scroll")
636
  async def interact_scroll(request: SessionRequest, auth=Depends(verify_token)):
637
  """Rola a página para baixo"""
@@ -655,6 +748,7 @@ async def interact_scroll(request: SessionRequest, auth=Depends(verify_token)):
655
  logger.error(f"[INTERACT-SCROLL] Erro: {e}")
656
  raise HTTPException(status_code=500, detail=str(e))
657
 
 
658
  @app.post("/interact/clear-and-type")
659
  async def interact_clear_and_type(request: InteractTypeRequest, auth=Depends(verify_token)):
660
  """Limpa o campo focado e digita novo texto"""
@@ -662,16 +756,18 @@ async def interact_clear_and_type(request: InteractTypeRequest, auth=Depends(ver
662
  driver = session['driver']
663
 
664
  try:
665
- driver.execute_script("""
666
- var el = document.activeElement;
667
- if (el && (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA')) {
668
- el.value = '';
669
- el.dispatchEvent(new Event('input', { bubbles: true }));
670
- el.value = arguments[0];
671
- el.dispatchEvent(new Event('input', { bubbles: true }));
672
- el.dispatchEvent(new Event('change', { bubbles: true }));
673
- }
674
- """, request.text)
 
 
675
 
676
  time.sleep(0.3)
677
 
@@ -690,6 +786,7 @@ async def interact_clear_and_type(request: InteractTypeRequest, auth=Depends(ver
690
  raise HTTPException(status_code=500, detail=str(e))
691
 
692
 
 
693
  # ============================================================
694
  # ROTAS DE BUSCA NO SITE
695
  # ============================================================
 
505
  driver = session['driver']
506
 
507
  try:
508
+ # Pegar tamanho real do viewport
509
+ viewport = driver.execute_script("""
510
+ return {
511
+ width: window.innerWidth,
512
+ height: window.innerHeight,
513
+ scrollX: window.scrollX,
514
+ scrollY: window.scrollY,
515
+ pageWidth: document.documentElement.scrollWidth,
516
+ pageHeight: document.documentElement.scrollHeight
517
+ };
518
+ """)
519
+
520
  screenshot = driver.get_screenshot_as_png()
521
  screenshot_b64 = base64.b64encode(screenshot).decode('utf-8')
522
 
523
  return {
524
  "screenshot": screenshot_b64,
525
+ "viewport": viewport,
526
  "url": driver.current_url,
527
  "title": driver.title
528
  }
 
530
  logger.error(f"[INTERACT-SCREENSHOT] Erro: {e}")
531
  raise HTTPException(status_code=500, detail=str(e))
532
 
533
+
534
  @app.post("/interact/click")
535
  async def interact_click(request: InteractClickRequest, auth=Depends(verify_token)):
536
+ """Clica em coordenada específica na página usando ActionChains"""
537
  session = session_manager.get_session(request.session_id)
538
  driver = session['driver']
539
 
540
  try:
541
+ x = request.x
542
+ y = request.y
 
 
 
 
 
 
 
 
 
 
543
 
544
+ # Método 1: ActionChains com offset desde o body
545
+ try:
546
+ body = driver.find_element(By.TAG_NAME, 'body')
547
+ actions = ActionChains(driver)
548
+ actions.move_to_element_with_offset(body, x - body.size['width'] // 2, y - body.size['height'] // 2)
549
+ actions.click()
550
+ actions.perform()
551
+ except Exception:
552
+ # Método 2: JavaScript com elementFromPoint + click + focus
553
+ driver.execute_script("""
554
+ var x = arguments[0];
555
+ var y = arguments[1];
556
+
557
+ // Scroll para a posição se necessário
558
+ var vpHeight = window.innerHeight;
559
+ if (y > vpHeight) {
560
+ window.scrollTo(0, y - vpHeight / 2);
561
+ y = vpHeight / 2;
562
+ }
563
+
564
+ var element = document.elementFromPoint(x, y);
565
+ if (element) {
566
+ // Simular eventos de mouse reais
567
+ var events = ['mousedown', 'mouseup', 'click'];
568
+ events.forEach(function(eventType) {
569
+ var event = new MouseEvent(eventType, {
570
+ view: window,
571
+ bubbles: true,
572
+ cancelable: true,
573
+ clientX: x,
574
+ clientY: y
575
+ });
576
+ element.dispatchEvent(event);
577
+ });
578
+
579
+ // Focar no elemento
580
+ if (element.focus) element.focus();
581
+
582
+ // Se for input/textarea, colocar cursor no final
583
+ if (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA') {
584
+ element.selectionStart = element.selectionEnd = element.value.length;
585
+ }
586
+ }
587
+ """, x, y)
588
+
589
+ time.sleep(0.8)
590
 
591
  screenshot = driver.get_screenshot_as_png()
592
  screenshot_b64 = base64.b64encode(screenshot).decode('utf-8')
593
 
594
+ # Verificar qual elemento está focado
595
+ focused = driver.execute_script("""
596
+ var el = document.activeElement;
597
+ if (el) {
598
+ return {
599
+ tag: el.tagName,
600
+ type: el.type || '',
601
+ id: el.id || '',
602
+ name: el.name || '',
603
+ isInput: (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA' || el.isContentEditable)
604
+ };
605
+ }
606
+ return null;
607
+ """)
608
+
609
  return {
610
  "status": "clicked",
611
  "x": request.x,
612
  "y": request.y,
613
+ "focused_element": focused,
614
  "screenshot": screenshot_b64,
615
  "url": driver.current_url,
616
  "title": driver.title
 
619
  logger.error(f"[INTERACT-CLICK] Erro: {e}")
620
  raise HTTPException(status_code=500, detail=str(e))
621
 
622
+
623
  @app.post("/interact/type")
624
  async def interact_type(request: InteractTypeRequest, auth=Depends(verify_token)):
625
+ """Digita texto no elemento focado usando ActionChains"""
626
  session = session_manager.get_session(request.session_id)
627
  driver = session['driver']
628
 
629
  try:
630
+ text = request.text
631
+
632
+ # Método 1: ActionChains (simula digitação real tecla por tecla)
633
+ try:
634
+ actions = ActionChains(driver)
635
+ actions.send_keys(text)
636
+ actions.perform()
637
+ except Exception:
638
+ # Método 2: JavaScript direto
639
+ driver.execute_script("""
640
+ var text = arguments[0];
641
+ var el = document.activeElement;
642
+ if (el && (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA' || el.isContentEditable)) {
643
+ if (el.isContentEditable) {
644
+ el.textContent += text;
645
+ } else {
646
+ var start = el.selectionStart || el.value.length;
647
+ var end = el.selectionEnd || el.value.length;
648
+ var before = el.value.substring(0, start);
649
+ var after = el.value.substring(end);
650
+ el.value = before + text + after;
651
+ el.selectionStart = el.selectionEnd = start + text.length;
652
+ }
653
+ el.dispatchEvent(new Event('input', { bubbles: true }));
654
+ el.dispatchEvent(new Event('change', { bubbles: true }));
655
+ // KeyUp para frameworks reativos
656
+ text.split('').forEach(function(char) {
657
+ el.dispatchEvent(new KeyboardEvent('keydown', { key: char, bubbles: true }));
658
+ el.dispatchEvent(new KeyboardEvent('keypress', { key: char, bubbles: true }));
659
+ el.dispatchEvent(new KeyboardEvent('keyup', { key: char, bubbles: true }));
660
+ });
661
+ }
662
+ """, text)
663
 
664
  time.sleep(0.3)
665
 
 
668
 
669
  return {
670
  "status": "typed",
671
+ "text": text,
672
  "screenshot": screenshot_b64,
673
  "url": driver.current_url,
674
  "title": driver.title
 
677
  logger.error(f"[INTERACT-TYPE] Erro: {e}")
678
  raise HTTPException(status_code=500, detail=str(e))
679
 
680
+
681
  @app.post("/interact/key")
682
  async def interact_key(request: InteractKeyRequest, auth=Depends(verify_token)):
683
+ """Pressiona tecla especial usando ActionChains"""
684
  session = session_manager.get_session(request.session_id)
685
  driver = session['driver']
686
 
 
703
  raise HTTPException(status_code=400, detail=f"Tecla não suportada: {request.key}")
704
 
705
  actions = ActionChains(driver)
706
+ actions.send_keys(key)
707
+ actions.perform()
708
 
709
+ time.sleep(0.8)
710
 
711
  screenshot = driver.get_screenshot_as_png()
712
  screenshot_b64 = base64.b64encode(screenshot).decode('utf-8')
 
724
  logger.error(f"[INTERACT-KEY] Erro: {e}")
725
  raise HTTPException(status_code=500, detail=str(e))
726
 
727
+
728
  @app.post("/interact/scroll")
729
  async def interact_scroll(request: SessionRequest, auth=Depends(verify_token)):
730
  """Rola a página para baixo"""
 
748
  logger.error(f"[INTERACT-SCROLL] Erro: {e}")
749
  raise HTTPException(status_code=500, detail=str(e))
750
 
751
+
752
  @app.post("/interact/clear-and-type")
753
  async def interact_clear_and_type(request: InteractTypeRequest, auth=Depends(verify_token)):
754
  """Limpa o campo focado e digita novo texto"""
 
756
  driver = session['driver']
757
 
758
  try:
759
+ # Limpar com Ctrl+A + Delete
760
+ actions = ActionChains(driver)
761
+ actions.key_down(Keys.CONTROL).send_keys('a').key_up(Keys.CONTROL)
762
+ actions.send_keys(Keys.DELETE)
763
+ actions.perform()
764
+
765
+ time.sleep(0.2)
766
+
767
+ # Digitar novo texto
768
+ actions = ActionChains(driver)
769
+ actions.send_keys(request.text)
770
+ actions.perform()
771
 
772
  time.sleep(0.3)
773
 
 
786
  raise HTTPException(status_code=500, detail=str(e))
787
 
788
 
789
+
790
  # ============================================================
791
  # ROTAS DE BUSCA NO SITE
792
  # ============================================================