THEZYZSTUDIO commited on
Commit
60fe7a4
ยท
verified ยท
1 Parent(s): f1d2b34

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +55 -46
app.py CHANGED
@@ -556,14 +556,17 @@ def run_command_smart(cmd: str, timeout: int = 60) -> dict:
556
  }
557
 
558
 
559
- def xdo(args: list, timeout=10) -> dict:
560
- r = subprocess.run(["xdotool"] + args,
561
- env={**os.environ, "DISPLAY": DISPLAY},
562
- timeout=timeout, capture_output=True, text=True)
563
- return {"rc": r.returncode, "out": r.stdout, "err": r.stderr}
 
 
 
564
 
565
 
566
- def type_text_smart(text: str) -> dict:
567
  """
568
  ูƒุชุงุจุฉ ู†ุต ุฐูƒูŠุฉ โ€” ุชุฏุนู… ุงู„ุนุฑุจูŠุฉ ูˆุงู„ุฅู†ุฌู„ูŠุฒูŠุฉ:
569
  - ู„ู„ู†ุตูˆุต ุงู„ุฅู†ุฌู„ูŠุฒูŠุฉ: xdotool type ู…ุจุงุดุฑุฉ
@@ -574,23 +577,25 @@ def type_text_smart(text: str) -> dict:
574
  if has_arabic:
575
  # ุทุฑูŠู‚ุฉ Clipboard ู„ุถู…ุงู† ูƒุชุงุจุฉ ุงู„ุนุฑุจูŠุฉ ุจุดูƒู„ ุตุญูŠุญ
576
  try:
577
- proc = subprocess.Popen(
578
- ["xclip", "-selection", "clipboard"],
579
- stdin=subprocess.PIPE,
580
- env={**os.environ, "DISPLAY": DISPLAY}
581
- )
582
- proc.communicate(text.encode("utf-8"))
583
- time.sleep(0.15)
 
 
584
  # Focus + paste
585
- xdo(["key", "--clearmodifiers", "ctrl+v"])
586
  return {"success": True, "method": "clipboard+paste", "arabic": True}
587
  except Exception as e:
588
  # fallback: xdotool type
589
- r = xdo(["type", "--clearmodifiers", "--delay", "50", text])
590
  return {"success": r["rc"] == 0, "method": "xdotool_fallback", "error": r["err"]}
591
  else:
592
  # ุฅู†ุฌู„ูŠุฒูŠุฉ: xdotool type ู…ุจุงุดุฑุฉ
593
- r = xdo(["type", "--clearmodifiers", "--delay", "30", text])
594
  return {"success": r["rc"] == 0, "method": "xdotool_direct"}
595
 
596
 
@@ -841,7 +846,7 @@ async def handle_action(ws: WebSocket, msg: dict):
841
  elif action == "mouse_move":
842
  x, y = int(data.get("x", 0)), int(data.get("y", 0))
843
  # --sync ูŠู†ุชุธุฑ ุญุชู‰ ูŠุคูƒุฏ X server ุงุณุชู„ุงู… ุงู„ุฃู…ุฑ
844
- xdo(["mousemove", "--sync", str(x), str(y)])
845
  await send({"type": "ack", "action": "mouse_move", "x": x, "y": y})
846
  # ู…ุฑู‘ุฑ ุงู„ุฅุญุฏุงุซูŠุงุช ู…ุจุงุดุฑุฉู‹ ู„ุชุฌู†ู‘ุจ race condition ู…ุน X server
847
  await auto_shot_grid(f"ู…ุงูˆุณ โ†’ ({x},{y})", delay=0.2,
@@ -851,12 +856,12 @@ async def handle_action(ws: WebSocket, msg: dict):
851
  elif action == "mouse_click":
852
  x, y = int(data.get("x", 0)), int(data.get("y", 0))
853
  btn_num = {"left": "1", "middle": "2", "right": "3"}.get(data.get("button", "left"), "1")
854
- xdo(["mousemove", "--sync", str(x), str(y)])
855
  await asyncio.sleep(0.08)
856
  if data.get("double"):
857
- xdo(["click", "--repeat", "2", "--delay", "100", btn_num])
858
  else:
859
- xdo(["click", btn_num])
860
  btn_name = {"1": "left", "2": "middle", "3": "right"}.get(btn_num, "left")
861
  await send({"type": "ack", "action": "mouse_click", "x": x, "y": y, "button": btn_name})
862
  # ู…ุฑู‘ุฑ ุงู„ุฅุญุฏุงุซูŠุงุช ู…ุจุงุดุฑุฉู‹ ู„ุชุฌู†ู‘ุจ race condition
@@ -867,7 +872,7 @@ async def handle_action(ws: WebSocket, msg: dict):
867
  elif action == "keyboard_type":
868
  text = data.get("text", "")
869
  if text:
870
- result = type_text_smart(text)
871
  await send({"type": "ack", "action": "keyboard_type",
872
  "method": result["method"], "text_len": len(text)})
873
  else:
@@ -878,7 +883,7 @@ async def handle_action(ws: WebSocket, msg: dict):
878
  elif action == "keyboard_hotkey":
879
  keys = data.get("keys", [])
880
  if keys:
881
- xdo(["key", "--clearmodifiers", "+".join(keys)])
882
  await send({"type": "ack", "action": "keyboard_hotkey", "keys": keys})
883
  await auto_shot_grid("ุจุนุฏ ุงู„ุงุฎุชุตุงุฑ", delay=0.5)
884
 
@@ -886,7 +891,7 @@ async def handle_action(ws: WebSocket, msg: dict):
886
  elif action == "keyboard_press":
887
  key = data.get("key", "")
888
  if key:
889
- xdo(["key", "--clearmodifiers", key])
890
  await send({"type": "ack", "action": "keyboard_press"})
891
  await auto_shot_grid("ุจุนุฏ ุงู„ู…ูุชุงุญ", delay=0.4)
892
 
@@ -894,19 +899,21 @@ async def handle_action(ws: WebSocket, msg: dict):
894
  elif action == "clipboard_write":
895
  text = data.get("text", "")
896
  try:
897
- proc = subprocess.Popen(
898
- ["xclip", "-selection", "clipboard"],
899
- stdin=subprocess.PIPE,
900
- env={**os.environ, "DISPLAY": DISPLAY}
901
- )
902
- proc.communicate(text.encode("utf-8"))
 
 
903
  await send({"type": "ack", "action": "clipboard_write", "length": len(text)})
904
  except Exception as e:
905
  await send({"type": "error", "action": "clipboard_write", "msg": str(e)})
906
 
907
  # โ”€โ”€ clipboard_read โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
908
  elif action == "clipboard_read":
909
- res = run_raw_command("xclip -selection clipboard -o", timeout=5)
910
  await send({"type": "clipboard_content", "text": res["stdout"]})
911
 
912
  # โ”€โ”€ scroll โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
@@ -914,9 +921,9 @@ async def handle_action(ws: WebSocket, msg: dict):
914
  x, y = int(data.get("x", 0)), int(data.get("y", 0))
915
  clicks = int(data.get("clicks", 3))
916
  btn = "4" if clicks > 0 else "5"
917
- xdo(["mousemove", str(x), str(y)])
918
  for _ in range(abs(clicks)):
919
- xdo(["click", btn])
920
  await asyncio.sleep(0.03)
921
  await send({"type": "ack", "action": "scroll", "clicks": clicks})
922
  await auto_shot_grid("ุจุนุฏ ุงู„ุชู…ุฑูŠุฑ", delay=0.4)
@@ -928,7 +935,7 @@ async def handle_action(ws: WebSocket, msg: dict):
928
  fixed_cmd = app_cmd
929
  # ุฅุตู„ุงุญ firefox-esr
930
  if "firefox-esr" in app_cmd:
931
- esr_check = subprocess.run(["which", "firefox-esr"], capture_output=True, text=True)
932
  if esr_check.returncode != 0:
933
  fixed_cmd = app_cmd.replace("firefox-esr", BROWSER)
934
 
@@ -961,12 +968,12 @@ async def handle_action(ws: WebSocket, msg: dict):
961
  elif action == "mouse_drag":
962
  x1, y1 = int(data.get("x1", 0)), int(data.get("y1", 0))
963
  x2, y2 = int(data.get("x2", 0)), int(data.get("y2", 0))
964
- xdo(["mousemove", str(x1), str(y1)])
965
- xdo(["mousedown", "1"])
966
  await asyncio.sleep(0.1)
967
- xdo(["mousemove", str(x2), str(y2)])
968
  await asyncio.sleep(0.1)
969
- xdo(["mouseup", "1"])
970
  await send({"type": "ack", "action": "mouse_drag"})
971
  # cursor ูŠู†ุชู‡ูŠ ุนู†ุฏ x2,y2
972
  await auto_shot_grid("ุจุนุฏ ุงู„ุณุญุจ", delay=0.4, force_mx=x2, force_my=y2)
@@ -989,8 +996,8 @@ async def handle_action(ws: WebSocket, msg: dict):
989
 
990
  # โ”€โ”€ screen_info โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
991
  elif action == "screen_info":
992
- w, h = _get_screen_size()
993
- mx, my = _get_mouse_pos()
994
  await send({
995
  "type": "screen_info",
996
  "width": w, "height": h,
@@ -1002,14 +1009,16 @@ async def handle_action(ws: WebSocket, msg: dict):
1002
  elif action == "paste":
1003
  text = data.get("text", "")
1004
  if text:
1005
- proc = subprocess.Popen(
1006
- ["xclip", "-selection", "clipboard"],
1007
- stdin=subprocess.PIPE,
1008
- env={**os.environ, "DISPLAY": DISPLAY}
1009
- )
1010
- proc.communicate(text.encode("utf-8"))
 
 
1011
  await asyncio.sleep(0.1)
1012
- xdo(["key", "--clearmodifiers", "ctrl+v"])
1013
  await send({"type": "ack", "action": "paste"})
1014
  await auto_shot_grid("ุจุนุฏ ุงู„ู„ุตู‚", delay=0.5)
1015
 
 
556
  }
557
 
558
 
559
+ async def xdo(args: list, timeout=10) -> dict:
560
+ """ูŠู†ูู‘ุฐ xdotool ููŠ thread ู…ู†ูุตู„ ุญุชู‰ ู„ุง ูŠูุฌู…ู‘ุฏ ุญู„ู‚ุฉ asyncio ุฃุซู†ุงุก ุงู„ุงู†ุชุธุงุฑ."""
561
+ def _run():
562
+ r = subprocess.run(["xdotool"] + args,
563
+ env={**os.environ, "DISPLAY": DISPLAY},
564
+ timeout=timeout, capture_output=True, text=True)
565
+ return {"rc": r.returncode, "out": r.stdout, "err": r.stderr}
566
+ return await asyncio.to_thread(_run)
567
 
568
 
569
+ async def type_text_smart(text: str) -> dict:
570
  """
571
  ูƒุชุงุจุฉ ู†ุต ุฐูƒูŠุฉ โ€” ุชุฏุนู… ุงู„ุนุฑุจูŠุฉ ูˆุงู„ุฅู†ุฌู„ูŠุฒูŠุฉ:
572
  - ู„ู„ู†ุตูˆุต ุงู„ุฅู†ุฌู„ูŠุฒูŠุฉ: xdotool type ู…ุจุงุดุฑุฉ
 
577
  if has_arabic:
578
  # ุทุฑูŠู‚ุฉ Clipboard ู„ุถู…ุงู† ูƒุชุงุจุฉ ุงู„ุนุฑุจูŠุฉ ุจุดูƒู„ ุตุญูŠุญ
579
  try:
580
+ def _xclip_write():
581
+ proc = subprocess.Popen(
582
+ ["xclip", "-selection", "clipboard"],
583
+ stdin=subprocess.PIPE,
584
+ env={**os.environ, "DISPLAY": DISPLAY}
585
+ )
586
+ proc.communicate(text.encode("utf-8"))
587
+ await asyncio.to_thread(_xclip_write)
588
+ await asyncio.sleep(0.15)
589
  # Focus + paste
590
+ await xdo(["key", "--clearmodifiers", "ctrl+v"])
591
  return {"success": True, "method": "clipboard+paste", "arabic": True}
592
  except Exception as e:
593
  # fallback: xdotool type
594
+ r = await xdo(["type", "--clearmodifiers", "--delay", "50", text])
595
  return {"success": r["rc"] == 0, "method": "xdotool_fallback", "error": r["err"]}
596
  else:
597
  # ุฅู†ุฌู„ูŠุฒูŠุฉ: xdotool type ู…ุจุงุดุฑุฉ
598
+ r = await xdo(["type", "--clearmodifiers", "--delay", "30", text])
599
  return {"success": r["rc"] == 0, "method": "xdotool_direct"}
600
 
601
 
 
846
  elif action == "mouse_move":
847
  x, y = int(data.get("x", 0)), int(data.get("y", 0))
848
  # --sync ูŠู†ุชุธุฑ ุญุชู‰ ูŠุคูƒุฏ X server ุงุณุชู„ุงู… ุงู„ุฃู…ุฑ
849
+ await xdo(["mousemove", "--sync", str(x), str(y)])
850
  await send({"type": "ack", "action": "mouse_move", "x": x, "y": y})
851
  # ู…ุฑู‘ุฑ ุงู„ุฅุญุฏุงุซูŠุงุช ู…ุจุงุดุฑุฉู‹ ู„ุชุฌู†ู‘ุจ race condition ู…ุน X server
852
  await auto_shot_grid(f"ู…ุงูˆุณ โ†’ ({x},{y})", delay=0.2,
 
856
  elif action == "mouse_click":
857
  x, y = int(data.get("x", 0)), int(data.get("y", 0))
858
  btn_num = {"left": "1", "middle": "2", "right": "3"}.get(data.get("button", "left"), "1")
859
+ await xdo(["mousemove", "--sync", str(x), str(y)])
860
  await asyncio.sleep(0.08)
861
  if data.get("double"):
862
+ await xdo(["click", "--repeat", "2", "--delay", "100", btn_num])
863
  else:
864
+ await xdo(["click", btn_num])
865
  btn_name = {"1": "left", "2": "middle", "3": "right"}.get(btn_num, "left")
866
  await send({"type": "ack", "action": "mouse_click", "x": x, "y": y, "button": btn_name})
867
  # ู…ุฑู‘ุฑ ุงู„ุฅุญุฏุงุซูŠุงุช ู…ุจุงุดุฑุฉู‹ ู„ุชุฌู†ู‘ุจ race condition
 
872
  elif action == "keyboard_type":
873
  text = data.get("text", "")
874
  if text:
875
+ result = await type_text_smart(text)
876
  await send({"type": "ack", "action": "keyboard_type",
877
  "method": result["method"], "text_len": len(text)})
878
  else:
 
883
  elif action == "keyboard_hotkey":
884
  keys = data.get("keys", [])
885
  if keys:
886
+ await xdo(["key", "--clearmodifiers", "+".join(keys)])
887
  await send({"type": "ack", "action": "keyboard_hotkey", "keys": keys})
888
  await auto_shot_grid("ุจุนุฏ ุงู„ุงุฎุชุตุงุฑ", delay=0.5)
889
 
 
891
  elif action == "keyboard_press":
892
  key = data.get("key", "")
893
  if key:
894
+ await xdo(["key", "--clearmodifiers", key])
895
  await send({"type": "ack", "action": "keyboard_press"})
896
  await auto_shot_grid("ุจุนุฏ ุงู„ู…ูุชุงุญ", delay=0.4)
897
 
 
899
  elif action == "clipboard_write":
900
  text = data.get("text", "")
901
  try:
902
+ def _xclip_write2():
903
+ proc = subprocess.Popen(
904
+ ["xclip", "-selection", "clipboard"],
905
+ stdin=subprocess.PIPE,
906
+ env={**os.environ, "DISPLAY": DISPLAY}
907
+ )
908
+ proc.communicate(text.encode("utf-8"))
909
+ await asyncio.to_thread(_xclip_write2)
910
  await send({"type": "ack", "action": "clipboard_write", "length": len(text)})
911
  except Exception as e:
912
  await send({"type": "error", "action": "clipboard_write", "msg": str(e)})
913
 
914
  # โ”€โ”€ clipboard_read โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
915
  elif action == "clipboard_read":
916
+ res = await asyncio.to_thread(run_raw_command, "xclip -selection clipboard -o", 5)
917
  await send({"type": "clipboard_content", "text": res["stdout"]})
918
 
919
  # โ”€โ”€ scroll โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
 
921
  x, y = int(data.get("x", 0)), int(data.get("y", 0))
922
  clicks = int(data.get("clicks", 3))
923
  btn = "4" if clicks > 0 else "5"
924
+ await xdo(["mousemove", str(x), str(y)])
925
  for _ in range(abs(clicks)):
926
+ await xdo(["click", btn])
927
  await asyncio.sleep(0.03)
928
  await send({"type": "ack", "action": "scroll", "clicks": clicks})
929
  await auto_shot_grid("ุจุนุฏ ุงู„ุชู…ุฑูŠุฑ", delay=0.4)
 
935
  fixed_cmd = app_cmd
936
  # ุฅุตู„ุงุญ firefox-esr
937
  if "firefox-esr" in app_cmd:
938
+ esr_check = await asyncio.to_thread(subprocess.run, ["which", "firefox-esr"], capture_output=True, text=True)
939
  if esr_check.returncode != 0:
940
  fixed_cmd = app_cmd.replace("firefox-esr", BROWSER)
941
 
 
968
  elif action == "mouse_drag":
969
  x1, y1 = int(data.get("x1", 0)), int(data.get("y1", 0))
970
  x2, y2 = int(data.get("x2", 0)), int(data.get("y2", 0))
971
+ await xdo(["mousemove", str(x1), str(y1)])
972
+ await xdo(["mousedown", "1"])
973
  await asyncio.sleep(0.1)
974
+ await xdo(["mousemove", str(x2), str(y2)])
975
  await asyncio.sleep(0.1)
976
+ await xdo(["mouseup", "1"])
977
  await send({"type": "ack", "action": "mouse_drag"})
978
  # cursor ูŠู†ุชู‡ูŠ ุนู†ุฏ x2,y2
979
  await auto_shot_grid("ุจุนุฏ ุงู„ุณุญุจ", delay=0.4, force_mx=x2, force_my=y2)
 
996
 
997
  # โ”€โ”€ screen_info โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
998
  elif action == "screen_info":
999
+ w, h = await asyncio.to_thread(_get_screen_size)
1000
+ mx, my = await asyncio.to_thread(_get_mouse_pos)
1001
  await send({
1002
  "type": "screen_info",
1003
  "width": w, "height": h,
 
1009
  elif action == "paste":
1010
  text = data.get("text", "")
1011
  if text:
1012
+ def _xclip_paste():
1013
+ proc = subprocess.Popen(
1014
+ ["xclip", "-selection", "clipboard"],
1015
+ stdin=subprocess.PIPE,
1016
+ env={**os.environ, "DISPLAY": DISPLAY}
1017
+ )
1018
+ proc.communicate(text.encode("utf-8"))
1019
+ await asyncio.to_thread(_xclip_paste)
1020
  await asyncio.sleep(0.1)
1021
+ await xdo(["key", "--clearmodifiers", "ctrl+v"])
1022
  await send({"type": "ack", "action": "paste"})
1023
  await auto_shot_grid("ุจุนุฏ ุงู„ู„ุตู‚", delay=0.5)
1024