Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -488,20 +488,24 @@ je_auto_control.execute_action([

| Category | Commands |
|---|---|
| Mouse | `AC_click_mouse`, `AC_set_mouse_position`, `AC_get_mouse_position`, `AC_press_mouse`, `AC_release_mouse`, `AC_mouse_scroll`, `AC_mouse_left`, `AC_mouse_right`, `AC_mouse_middle` |
| Keyboard | `AC_type_keyboard`, `AC_press_keyboard_key`, `AC_release_keyboard_key`, `AC_write`, `AC_hotkey`, `AC_check_key_is_press` |
| Mouse | `AC_click_mouse`, `AC_set_mouse_position`, `AC_get_mouse_position`, `AC_get_mouse_table`, `AC_press_mouse`, `AC_release_mouse`, `AC_mouse_scroll`, `AC_mouse_left`, `AC_mouse_right`, `AC_mouse_middle` |
| Keyboard | `AC_type_keyboard`, `AC_press_keyboard_key`, `AC_release_keyboard_key`, `AC_write`, `AC_hotkey`, `AC_check_key_is_press`, `AC_get_keyboard_keys_table` |
| Image | `AC_locate_all_image`, `AC_locate_image_center`, `AC_locate_and_click` |
| Screen | `AC_screen_size`, `AC_screenshot` |
| Accessibility | `AC_a11y_list`, `AC_a11y_find`, `AC_a11y_click` |
| VLM (AI Locator) | `AC_vlm_locate`, `AC_vlm_click` |
| OCR | `AC_locate_text`, `AC_click_text`, `AC_wait_text` |
| Clipboard | `AC_clipboard_get`, `AC_clipboard_set` |
| Record | `AC_record`, `AC_stop_record` |
| Window | `AC_list_windows`, `AC_focus_window`, `AC_wait_window`, `AC_close_window` |
| Flow control | `AC_loop`, `AC_break`, `AC_continue`, `AC_if_image_found`, `AC_if_pixel`, `AC_while_image`, `AC_wait_image`, `AC_wait_pixel`, `AC_sleep`, `AC_retry` |
| Record | `AC_record`, `AC_stop_record`, `AC_set_record_enable` |
| Report | `AC_generate_html`, `AC_generate_json`, `AC_generate_xml`, `AC_generate_html_report`, `AC_generate_json_report`, `AC_generate_xml_report` |
| Run history | `AC_history_list`, `AC_history_clear` |
| Project | `AC_create_project` |
| Shell | `AC_shell_command` |
| Process | `AC_execute_process` |
| Executor | `AC_execute_action`, `AC_execute_files` |
| Executor | `AC_execute_action`, `AC_execute_files`, `AC_add_package_to_executor`, `AC_add_package_to_callback_executor` |
| MCP server | `AC_start_mcp_server`, `AC_start_mcp_http_server` |

### MCP Server (Use AutoControl from Claude)

Expand Down
12 changes: 8 additions & 4 deletions README/README_zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -482,20 +482,24 @@ je_auto_control.execute_action([

| 类别 | 命令 |
|---|---|
| 鼠标 | `AC_click_mouse`, `AC_set_mouse_position`, `AC_get_mouse_position`, `AC_press_mouse`, `AC_release_mouse`, `AC_mouse_scroll`, `AC_mouse_left`, `AC_mouse_right`, `AC_mouse_middle` |
| 键盘 | `AC_type_keyboard`, `AC_press_keyboard_key`, `AC_release_keyboard_key`, `AC_write`, `AC_hotkey`, `AC_check_key_is_press` |
| 鼠标 | `AC_click_mouse`, `AC_set_mouse_position`, `AC_get_mouse_position`, `AC_get_mouse_table`, `AC_press_mouse`, `AC_release_mouse`, `AC_mouse_scroll`, `AC_mouse_left`, `AC_mouse_right`, `AC_mouse_middle` |
| 键盘 | `AC_type_keyboard`, `AC_press_keyboard_key`, `AC_release_keyboard_key`, `AC_write`, `AC_hotkey`, `AC_check_key_is_press`, `AC_get_keyboard_keys_table` |
| 图像 | `AC_locate_all_image`, `AC_locate_image_center`, `AC_locate_and_click` |
| 屏幕 | `AC_screen_size`, `AC_screenshot` |
| Accessibility | `AC_a11y_list`, `AC_a11y_find`, `AC_a11y_click` |
| VLM(AI 定位) | `AC_vlm_locate`, `AC_vlm_click` |
| OCR | `AC_locate_text`, `AC_click_text`, `AC_wait_text` |
| 剪贴板 | `AC_clipboard_get`, `AC_clipboard_set` |
| 录制 | `AC_record`, `AC_stop_record` |
| 窗口 | `AC_list_windows`, `AC_focus_window`, `AC_wait_window`, `AC_close_window` |
| 流程控制 | `AC_loop`, `AC_break`, `AC_continue`, `AC_if_image_found`, `AC_if_pixel`, `AC_while_image`, `AC_wait_image`, `AC_wait_pixel`, `AC_sleep`, `AC_retry` |
| 录制 | `AC_record`, `AC_stop_record`, `AC_set_record_enable` |
| 报告 | `AC_generate_html`, `AC_generate_json`, `AC_generate_xml`, `AC_generate_html_report`, `AC_generate_json_report`, `AC_generate_xml_report` |
| 执行记录 | `AC_history_list`, `AC_history_clear` |
| 项目 | `AC_create_project` |
| Shell | `AC_shell_command` |
| 进程 | `AC_execute_process` |
| 执行器 | `AC_execute_action`, `AC_execute_files` |
| 执行器 | `AC_execute_action`, `AC_execute_files`, `AC_add_package_to_executor`, `AC_add_package_to_callback_executor` |
| MCP 服务器 | `AC_start_mcp_server`, `AC_start_mcp_http_server` |

### MCP 服务器(让 Claude 使用 AutoControl)

Expand Down
12 changes: 8 additions & 4 deletions README/README_zh-TW.md
Original file line number Diff line number Diff line change
Expand Up @@ -482,20 +482,24 @@ je_auto_control.execute_action([

| 類別 | 命令 |
|---|---|
| 滑鼠 | `AC_click_mouse`, `AC_set_mouse_position`, `AC_get_mouse_position`, `AC_press_mouse`, `AC_release_mouse`, `AC_mouse_scroll`, `AC_mouse_left`, `AC_mouse_right`, `AC_mouse_middle` |
| 鍵盤 | `AC_type_keyboard`, `AC_press_keyboard_key`, `AC_release_keyboard_key`, `AC_write`, `AC_hotkey`, `AC_check_key_is_press` |
| 滑鼠 | `AC_click_mouse`, `AC_set_mouse_position`, `AC_get_mouse_position`, `AC_get_mouse_table`, `AC_press_mouse`, `AC_release_mouse`, `AC_mouse_scroll`, `AC_mouse_left`, `AC_mouse_right`, `AC_mouse_middle` |
| 鍵盤 | `AC_type_keyboard`, `AC_press_keyboard_key`, `AC_release_keyboard_key`, `AC_write`, `AC_hotkey`, `AC_check_key_is_press`, `AC_get_keyboard_keys_table` |
| 圖像 | `AC_locate_all_image`, `AC_locate_image_center`, `AC_locate_and_click` |
| 螢幕 | `AC_screen_size`, `AC_screenshot` |
| Accessibility | `AC_a11y_list`, `AC_a11y_find`, `AC_a11y_click` |
| VLM(AI 定位) | `AC_vlm_locate`, `AC_vlm_click` |
| OCR | `AC_locate_text`, `AC_click_text`, `AC_wait_text` |
| 剪貼簿 | `AC_clipboard_get`, `AC_clipboard_set` |
| 錄製 | `AC_record`, `AC_stop_record` |
| 視窗 | `AC_list_windows`, `AC_focus_window`, `AC_wait_window`, `AC_close_window` |
| 流程控制 | `AC_loop`, `AC_break`, `AC_continue`, `AC_if_image_found`, `AC_if_pixel`, `AC_while_image`, `AC_wait_image`, `AC_wait_pixel`, `AC_sleep`, `AC_retry` |
| 錄製 | `AC_record`, `AC_stop_record`, `AC_set_record_enable` |
| 報告 | `AC_generate_html`, `AC_generate_json`, `AC_generate_xml`, `AC_generate_html_report`, `AC_generate_json_report`, `AC_generate_xml_report` |
| 執行紀錄 | `AC_history_list`, `AC_history_clear` |
| 專案 | `AC_create_project` |
| Shell | `AC_shell_command` |
| 程序 | `AC_execute_process` |
| 執行器 | `AC_execute_action`, `AC_execute_files` |
| 執行器 | `AC_execute_action`, `AC_execute_files`, `AC_add_package_to_executor`, `AC_add_package_to_callback_executor` |
| MCP 伺服器 | `AC_start_mcp_server`, `AC_start_mcp_http_server` |

### MCP 伺服器(讓 Claude 使用 AutoControl)

Expand Down
11 changes: 5 additions & 6 deletions je_auto_control/utils/callback/callback_function_executor.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Callable, Any
from typing import Any, Callable

# utils cv2_utils
from je_auto_control.utils.cv2_utils.screenshot import pil_screenshot
Expand All @@ -7,6 +7,7 @@
from je_auto_control.utils.logging.logging_instance import autocontrol_logger
# executor
from je_auto_control.utils.executor.action_executor import execute_action, execute_files
from je_auto_control.utils.executor.mouse_aliases import MOUSE_BUTTON_COMMANDS
# file process
from je_auto_control.utils.file_process.get_dir_file_list import get_dir_files_as_list
# html report
Expand All @@ -22,7 +23,7 @@
# project
from je_auto_control.utils.project.create_project_structure import create_project_dir
# shell
from je_auto_control.utils.shell_process.shell_exec import ShellManager
from je_auto_control.utils.shell_process.shell_exec import default_shell_manager
# socket server
from je_auto_control.utils.socket_server.auto_control_socket_server import start_autocontrol_socket_server
# process
Expand Down Expand Up @@ -61,9 +62,7 @@ def __init__(self):
# 事件字典,對應字串名稱到實際函式
self.event_dict: dict = {
# mouse 滑鼠相關
"AC_mouse_left": click_mouse,
"AC_mouse_right": click_mouse,
"AC_mouse_middle": click_mouse,
**MOUSE_BUTTON_COMMANDS,
"AC_click_mouse": click_mouse,
"AC_get_mouse_table": get_mouse_table,
"AC_get_mouse_position": get_mouse_position,
Expand Down Expand Up @@ -129,7 +128,7 @@ def __init__(self):
"AC_add_package_to_callback_executor": package_manager.add_package_to_callback_executor,

# shell command
"AC_shell_command": ShellManager().exec_shell,
"AC_shell_command": default_shell_manager.exec_shell,

# process
"AC_execute_process": start_exe,
Expand Down
9 changes: 4 additions & 5 deletions je_auto_control/utils/executor/action_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from je_auto_control.utils.executor.flow_control import (
BLOCK_COMMANDS, LoopBreak, LoopContinue,
)
from je_auto_control.utils.executor.mouse_aliases import MOUSE_BUTTON_COMMANDS
from je_auto_control.utils.ocr.ocr_engine import (
click_text as ocr_click_text,
locate_text_center as ocr_locate_text_center,
Expand All @@ -38,7 +39,7 @@
from je_auto_control.utils.mcp_server.server import start_mcp_stdio_server
from je_auto_control.utils.package_manager.package_manager_class import package_manager
from je_auto_control.utils.project.create_project_structure import create_project_dir
from je_auto_control.utils.shell_process.shell_exec import ShellManager
from je_auto_control.utils.shell_process.shell_exec import default_shell_manager
from je_auto_control.utils.start_exe.start_another_process import start_exe
from je_auto_control.utils.test_record.record_test_class import record_action_to_list, test_record_instance
from je_auto_control.wrapper.auto_control_image import locate_all_image, locate_and_click, locate_image_center
Expand Down Expand Up @@ -124,9 +125,7 @@ def __init__(self):
# 事件字典,對應字串名稱到函式
self.event_dict: dict = {
# Mouse 滑鼠相關
"AC_mouse_left": click_mouse,
"AC_mouse_right": click_mouse,
"AC_mouse_middle": click_mouse,
**MOUSE_BUTTON_COMMANDS,
"AC_click_mouse": click_mouse,
"AC_get_mouse_table": get_mouse_table,
"AC_get_mouse_position": get_mouse_position,
Expand Down Expand Up @@ -178,7 +177,7 @@ def __init__(self):
"AC_create_project": create_project_dir,

# Shell
"AC_shell_command": ShellManager().exec_shell,
"AC_shell_command": default_shell_manager.exec_shell,

# Process
"AC_execute_process": start_exe,
Expand Down
39 changes: 39 additions & 0 deletions je_auto_control/utils/executor/mouse_aliases.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""Single-button mouse-click aliases shared by the action and callback executors.

Each ``AC_mouse_<button>`` command name needs a callable whose signature is
``(x=None, y=None)`` so the button itself is implied by the command name and
not threaded through ``mouse_keycode``. Generating the three callables from
one factory keeps the registration sites identical across executors.
"""
from typing import Callable, Optional, Tuple

from je_auto_control.wrapper.auto_control_mouse import click_mouse

ClickFn = Callable[[Optional[int], Optional[int]], Tuple[int, int, int]]


def _make_button_click(button: str) -> ClickFn:
def click(x: Optional[int] = None,
y: Optional[int] = None) -> Tuple[int, int, int]:
return click_mouse(button, x, y)

click.__name__ = f"click_{button}"
click.__qualname__ = click.__name__
click.__doc__ = f"Click the {button.replace('_', ' ')} mouse button at (x, y)."
return click


click_mouse_left: ClickFn = _make_button_click("mouse_left")
click_mouse_right: ClickFn = _make_button_click("mouse_right")
click_mouse_middle: ClickFn = _make_button_click("mouse_middle")

MOUSE_BUTTON_COMMANDS: dict = {
"AC_mouse_left": click_mouse_left,
"AC_mouse_right": click_mouse_right,
"AC_mouse_middle": click_mouse_middle,
}

__all__ = [
"click_mouse_left", "click_mouse_right", "click_mouse_middle",
"MOUSE_BUTTON_COMMANDS",
]
22 changes: 1 addition & 21 deletions je_auto_control/wrapper/auto_control_image.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from typing import List, Tuple, Optional, Union
from typing import List, Tuple, Union

from je_auto_control.utils.cv2_utils import template_detection
from je_auto_control.utils.cv2_utils.screenshot import pil_screenshot
from je_auto_control.utils.exception.exception_tags import cant_find_image_error_message
from je_auto_control.utils.exception.exceptions import ImageNotFoundException
from je_auto_control.utils.logging.logging_instance import autocontrol_logger
Expand Down Expand Up @@ -81,23 +80,4 @@ def locate_and_click(image, mouse_keycode: Union[int, str],
except (OSError, RuntimeError, AttributeError, TypeError, ValueError, ImageNotFoundException) as error:
record_action_to_list("locate_and_click", {"image": image}, repr(error))
autocontrol_logger.error(f"locate_and_click failed: {repr(error)}")
raise


def screenshot(file_path: Optional[str] = None, region: Optional[List[int]] = None):
"""
擷取螢幕畫面
Take a screenshot

:param file_path: 儲存路徑 (None = 不儲存)
:param region: 擷取區域 [x1, y1, x2, y2]
:return: PIL Image
"""
autocontrol_logger.info(f"screenshot, file={file_path}, region={region}")
try:
record_action_to_list("screenshot", {"file_path": file_path, "region": region})
return pil_screenshot(file_path, region)
except (OSError, RuntimeError, AttributeError, TypeError, ValueError, ImageNotFoundException) as error:
record_action_to_list("screenshot", {"file_path": file_path, "region": region}, repr(error))
autocontrol_logger.error(f"screenshot failed: {repr(error)}")
raise
2 changes: 1 addition & 1 deletion je_auto_control/wrapper/auto_control_record.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def stop_record() -> list:
if action[0] == "AC_type_keyboard":
new_list.append([action[0], {"keycode": action[1]}])
else:
new_list.append([action[0], {"mouse_keycode": action[0], "x": action[1], "y": action[2]}])
new_list.append([action[0], {"x": action[1], "y": action[2]}])
record_action_to_list("stop_record", None)
return new_list
except (OSError, RuntimeError, AttributeError, TypeError, ValueError, AutoControlException, AutoControlJsonActionException) as error:
Expand Down
1 change: 0 additions & 1 deletion test/unit_test/argparse/test1.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
[
"AC_mouse_left",
{
"mouse_keycode": "mouse_left",
"x": 500,
"y": 500
}
Expand Down
1 change: 0 additions & 1 deletion test/unit_test/argparse/test2.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
[
"AC_mouse_left",
{
"mouse_keycode": "mouse_left",
"x": 500,
"y": 500
}
Expand Down
6 changes: 3 additions & 3 deletions test/unit_test/execute_action/execute_action_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
if sys.platform in ["win32", "cygwin", "msys"]:
test_list = [
["AC_type_keyboard", {"keycode": 65}],
["AC_mouse_left", {"mouse_keycode": "mouse_left", "x": 500, "y": 500}],
["AC_mouse_left", {"x": 500, "y": 500}],
["AC_get_mouse_position"],
["AC_press_mouse", {"mouse_keycode": "mouse_left", "x": 500, "y": 500}],
["AC_release_mouse", {"mouse_keycode": "mouse_left", "x": 500, "y": 500}],
Expand All @@ -18,7 +18,7 @@
elif sys.platform in ["linux", "linux2"]:
test_list = [
["AC_type_keyboard", {"keycode": 38}],
["AC_mouse_left", {"mouse_keycode": "mouse_left", "x": 500, "y": 500}],
["AC_mouse_left", {"x": 500, "y": 500}],
["AC_get_mouse_position"],
["AC_press_mouse", {"mouse_keycode": "mouse_left", "x": 500, "y": 500}],
["AC_release_mouse", {"mouse_keycode": "mouse_left", "x": 500, "y": 500}],
Expand All @@ -27,7 +27,7 @@
elif sys.platform in ["darwin"]:
test_list = [
["AC_type_keyboard", {"keycode": 0x00}],
["AC_mouse_left", {"mouse_keycode": "mouse_left", "x": 500, "y": 500}],
["AC_mouse_left", {"x": 500, "y": 500}],
["AC_get_mouse_position"],
["AC_press_mouse", {"mouse_keycode": "mouse_left", "x": 500, "y": 500}],
["AC_release_mouse", {"mouse_keycode": "mouse_left", "x": 500, "y": 500}],
Expand Down
44 changes: 2 additions & 42 deletions test/unit_test/generate_report/html_report_test.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,3 @@
import sys
from report_smoke import run_report_smoke

from je_auto_control import execute_action
from je_auto_control import test_record_instance

test_list = None
test_record_instance.init_record = True
if sys.platform in ["win32", "cygwin", "msys"]:
test_list = [
["AC_set_record_enable", {"set_enable": True}],
["AC_type_keyboard", {"keycode": 65}],
["AC_mouse_left", {"mouse_keycode": "AC_mouse_left", "x": 500, "y": 500}],
["AC_get_mouse_position"],
["AC_press_mouse", {"mouse_keycode": "AC_mouse_left", "x": 500, "y": 500}],
["AC_release_mouse", {"mouse_keycode": "AC_mouse_left", "x": 500, "y": 500}],
["AC_type_keyboard", {"mouse_keycode": "dwadwawda", "dwadwad": 500, "wdawddwawad": 500}],
["AC_generate_html_report"],
]

elif sys.platform in ["linux", "linux2"]:
test_list = [
["AC_set_record_enable", {"set_enable": True}],
["AC_type_keyboard", {"keycode": 38}],
["AC_mouse_left", {"mouse_keycode": "AC_mouse_left", "x": 500, "y": 500}],
["AC_get_mouse_position"],
["AC_press_mouse", {"mouse_keycode": "AC_mouse_left", "x": 500, "y": 500}],
["AC_release_mouse", {"mouse_keycode": "AC_mouse_left", "x": 500, "y": 500}],
["AC_type_keyboard", {"mouse_keycode": "dwadwawda", "dwadwad": 500, "wdawddwawad": 500}],
["AC_generate_html_report"],
]
elif sys.platform in ["darwin"]:
test_list = [
["AC_set_record_enable", {"set_enable": True}],
["AC_type_keyboard", {"keycode": 0x00}],
["AC_mouse_left", {"mouse_keycode": "AC_mouse_left", "x": 500, "y": 500}],
["AC_get_mouse_position"],
["AC_press_mouse", {"mouse_keycode": "AC_mouse_left", "x": 500, "y": 500}],
["AC_release_mouse", {"mouse_keycode": "AC_mouse_left", "x": 500, "y": 500}],
["AC_type_keyboard", {"mouse_keycode": "dwadwawda", "dwadwad": 500, "wdawddwawad": 500}],
["AC_generate_html_report"],
]
print("\n\n")
execute_action(test_list)
run_report_smoke("AC_generate_html_report")
44 changes: 2 additions & 42 deletions test/unit_test/generate_report/json_report.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,3 @@
import sys
from report_smoke import run_report_smoke

from je_auto_control import execute_action
from je_auto_control import test_record_instance

test_list = None
test_record_instance.init_record = True
if sys.platform in ["win32", "cygwin", "msys"]:
test_list = [
["AC_set_record_enable", {"set_enable": True}],
["AC_type_keyboard", {"keycode": 65}],
["AC_mouse_left", {"mouse_keycode": "AC_mouse_left", "x": 500, "y": 500}],
["AC_get_mouse_position"],
["AC_press_mouse", {"mouse_keycode": "AC_mouse_left", "x": 500, "y": 500}],
["AC_release_mouse", {"mouse_keycode": "AC_mouse_left", "x": 500, "y": 500}],
["AC_type_keyboard", {"mouse_keycode": "dwadwawda", "dwadwad": 500, "wdawddwawad": 500}],
["AC_generate_json_report"],
]

elif sys.platform in ["linux", "linux2"]:
test_list = [
["AC_set_record_enable", {"set_enable": True}],
["AC_type_keyboard", {"keycode": 38}],
["AC_mouse_left", {"mouse_keycode": "AC_mouse_left", "x": 500, "y": 500}],
["AC_get_mouse_position"],
["AC_press_mouse", {"mouse_keycode": "AC_mouse_left", "x": 500, "y": 500}],
["AC_release_mouse", {"mouse_keycode": "AC_mouse_left", "x": 500, "y": 500}],
["AC_type_keyboard", {"mouse_keycode": "dwadwawda", "dwadwad": 500, "wdawddwawad": 500}],
["AC_generate_json_report"],
]
elif sys.platform in ["darwin"]:
test_list = [
["AC_set_record_enable", {"set_enable": True}],
["AC_type_keyboard", {"keycode": 0x00}],
["AC_mouse_left", {"mouse_keycode": "AC_mouse_left", "x": 500, "y": 500}],
["AC_get_mouse_position"],
["AC_press_mouse", {"mouse_keycode": "AC_mouse_left", "x": 500, "y": 500}],
["AC_release_mouse", {"mouse_keycode": "AC_mouse_left", "x": 500, "y": 500}],
["AC_type_keyboard", {"mouse_keycode": "dwadwawda", "dwadwad": 500, "wdawddwawad": 500}],
["AC_generate_json_report"],
]
print("\n\n")
execute_action(test_list)
run_report_smoke("AC_generate_json_report")
Loading
Loading