Spaces:
Paused
Paused
Update app.py
Browse files
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 |
-
|
| 561 |
-
|
| 562 |
-
|
| 563 |
-
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
| 578 |
-
|
| 579 |
-
|
| 580 |
-
|
| 581 |
-
|
| 582 |
-
|
| 583 |
-
|
|
|
|
|
|
|
| 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 |
-
|
| 898 |
-
|
| 899 |
-
|
| 900 |
-
|
| 901 |
-
|
| 902 |
-
|
|
|
|
|
|
|
| 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 =
|
| 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
|
| 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 =
|
| 993 |
-
mx, my =
|
| 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 |
-
|
| 1006 |
-
|
| 1007 |
-
|
| 1008 |
-
|
| 1009 |
-
|
| 1010 |
-
|
|
|
|
|
|
|
| 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 |
|