diff --git a/.idea/workspace.xml b/.idea/workspace.xml index b78a289..ffe893d 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -3,8 +3,18 @@ + + + + + + + + + + - - + + - + - + - + - + - + - - + + + + - - @@ -275,6 +285,7 @@ + @@ -289,6 +300,7 @@ + \ No newline at end of file diff --git a/je_auto_control/__init__.py b/je_auto_control/__init__.py index 07dcc7a..cbdbeec 100644 --- a/je_auto_control/__init__.py +++ b/je_auto_control/__init__.py @@ -40,3 +40,7 @@ from je_auto_control.utils.je_auto_control_exception.exceptions import AutoControlCantFindKeyException from je_auto_control.utils.je_auto_control_exception.exceptions import AutoControlScreenException from je_auto_control.utils.je_auto_control_exception.exceptions import ImageNotFoundException + +# record +from je_auto_control.wrapper.auto_control_record import record +from je_auto_control.wrapper.auto_control_record import stop_record diff --git a/je_auto_control/linux_with_x11/listener/x11_linux_listener.py b/je_auto_control/linux_with_x11/listener/x11_linux_listener.py index 5ae2556..91e8f4c 100644 --- a/je_auto_control/linux_with_x11/listener/x11_linux_listener.py +++ b/je_auto_control/linux_with_x11/listener/x11_linux_listener.py @@ -10,8 +10,6 @@ from Xlib.ext import record from Xlib.protocol import rq -from je_auto_control.linux_with_x11.mouse.x11_linux_mouse_control import position - from threading import Thread # get current display @@ -29,6 +27,8 @@ def __init__(self, default_daemon=True): super().__init__() self.setDaemon(default_daemon) self.still_listener = True + self.record_flag = False + self.record_queue = None self.event_keycode = 0 self.event_position = 0, 0 @@ -55,14 +55,24 @@ def run(self, reply): data = reply.data while len(data) and self.still_listener: event, data = rq.EventField(None).parse_binary_value(data, current_display.display, None, None) - # run two times because press and release event if event.detail != 0: - self.event_keycode = event.detail - self.event_position = event.root_x, event.root_y - + if event.type is X.ButtonRelease or event.type is X.KeyRelease: + self.event_keycode = event.detail + self.event_position = event.root_x, event.root_y + if self.record_flag is True: + temp = (event.type, event.detail, event.root_x, event.root_y) + self.record_queue.put(temp) except Exception: raise Exception + def record(self, record_queue): + self.record_flag = True + self.record_queue = record_queue + + def stop_record(self): + self.record_flag = False + return self.record_queue + class XWindowsKeypressListener(Thread): @@ -121,6 +131,12 @@ def run(self): self.handler.still_listener = False self.still_listener = False + def record(self, record_queue): + self.handler.record(record_queue) + + def stop_record(self): + return self.handler.stop_record() + xwindows_listener = XWindowsKeypressListener() xwindows_listener.start() @@ -133,6 +149,17 @@ def check_key_is_press(keycode): return xwindows_listener.check_is_press(keycode) +def x11_linux_record(record_queue): + xwindows_listener.record(record_queue) + + +def x11_linux_stop_record(): + return xwindows_listener.stop_record() + + if __name__ == "__main__": + from queue import Queue + test_queue = Queue() + xwindows_listener.record(test_queue) while True: pass diff --git a/je_auto_control/linux_with_x11/mouse/x11_linux_mouse_control.py b/je_auto_control/linux_with_x11/mouse/x11_linux_mouse_control.py index 4cdb6ce..6f8600f 100644 --- a/je_auto_control/linux_with_x11/mouse/x11_linux_mouse_control.py +++ b/je_auto_control/linux_with_x11/mouse/x11_linux_mouse_control.py @@ -50,10 +50,14 @@ def release_mouse(mouse_keycode): display.sync() -def click_mouse(mouse_keycode): +def click_mouse(mouse_keycode, x=None, y=None): """ :param mouse_keycode which mouse keycode we want to click + :param x set mouse x position + :param y set mouse y position """ + if x and y is not None: + set_position(x, y) press_mouse(mouse_keycode) release_mouse(mouse_keycode) diff --git a/je_auto_control/linux_with_x11/record/x11_linux_record.py b/je_auto_control/linux_with_x11/record/x11_linux_record.py new file mode 100644 index 0000000..2e0f883 --- /dev/null +++ b/je_auto_control/linux_with_x11/record/x11_linux_record.py @@ -0,0 +1,49 @@ +import sys + +if sys.platform not in ["linux", "linux2"]: + raise Exception("should be only loaded on linux") + +from Xlib import X + +from je_auto_control.linux_with_x11.listener.x11_linux_listener import x11_linux_record +from je_auto_control.linux_with_x11.listener.x11_linux_listener import x11_linux_stop_record + +from queue import Queue + +type_dict = {5: "mouse", 3: "keyboard"} +detail_dict = {1: "mouse_left", 2: "mouse_middle", 3: "mouse_right"} + + +class X11LinuxRecorder(object): + + def __init__(self): + self.record_queue = None + self.result_queue = None + + def record(self): + self.record_queue = Queue() + x11_linux_record(self.record_queue) + + def stop_record(self): + self.result_queue = x11_linux_stop_record() + action_queue = Queue() + for details in self.result_queue.queue: + if details[0] == 5: + action_queue.put((detail_dict.get(details[1]), details[2], details[3])) + elif details[0] == 3: + action_queue.put((type_dict.get(details[0]), details[1])) + return action_queue + + +x11_linux_recoder = X11LinuxRecorder() + + +if __name__ == "__main__": + x11_record = X11LinuxRecorder() + x11_record.record() + from time import sleep + sleep(10) + temp = x11_record.stop_record() + for action in temp.queue: + print(action) + diff --git a/je_auto_control/osx/keyboard/osx_keyboard_listener.py b/je_auto_control/osx/keyboard/osx_keyboard_check.py similarity index 100% rename from je_auto_control/osx/keyboard/osx_keyboard_listener.py rename to je_auto_control/osx/keyboard/osx_keyboard_check.py diff --git a/je_auto_control/osx/mouse/osx_mouse.py b/je_auto_control/osx/mouse/osx_mouse.py index 080d7cb..fe2e2e5 100644 --- a/je_auto_control/osx/mouse/osx_mouse.py +++ b/je_auto_control/osx/mouse/osx_mouse.py @@ -38,7 +38,7 @@ def set_position(x, y): mouse_event(Quartz.kCGEventMouseMoved, x, y, 0) -def press_mouse(x, y, mouse_button): +def press_mouse(mouse_button, x, y): """ :param x event x :param y event y diff --git a/je_auto_control/utils/critical_exit/critcal_exit.py b/je_auto_control/utils/critical_exit/critcal_exit.py index cbd3393..ee51e3d 100644 --- a/je_auto_control/utils/critical_exit/critcal_exit.py +++ b/je_auto_control/utils/critical_exit/critcal_exit.py @@ -5,7 +5,7 @@ from je_auto_control.utils.je_auto_control_exception.exception_tag import je_auto_control_critical_exit_error from je_auto_control.utils.je_auto_control_exception.exceptions import AutoControlException from je_auto_control.wrapper.auto_control_keyboard import keys_table -from je_auto_control.wrapper.platform_wrapper import keyboard_listener +from je_auto_control.wrapper.platform_wrapper import keyboard_check class CriticalExit(Thread): @@ -30,7 +30,7 @@ def run(self): """ try: while True: - if keyboard_listener.check_key_is_press(self._exit_check_key): + if keyboard_check.check_key_is_press(self._exit_check_key): _thread.interrupt_main() except AutoControlException: raise AutoControlException(je_auto_control_critical_exit_error) diff --git a/je_auto_control/utils/je_auto_control_exception/exception_tag.py b/je_auto_control/utils/je_auto_control_exception/exception_tag.py index a0c39c3..46f9a3b 100644 --- a/je_auto_control/utils/je_auto_control_exception/exception_tag.py +++ b/je_auto_control/utils/je_auto_control_exception/exception_tag.py @@ -38,3 +38,8 @@ """ cant_find_image = "can't find image" find_image_error_variable = "variable error" +""" +record tags +""" +record_queue_error = "can't get record queue it's none are you using stop record before record" +record_not_found_action_error = "record action not found" diff --git a/je_auto_control/utils/je_auto_control_exception/exceptions.py b/je_auto_control/utils/je_auto_control_exception/exceptions.py index 75a7915..63fe20e 100644 --- a/je_auto_control/utils/je_auto_control_exception/exceptions.py +++ b/je_auto_control/utils/je_auto_control_exception/exceptions.py @@ -4,6 +4,7 @@ from je_auto_control.utils.je_auto_control_exception.exception_tag import keyboard_error from je_auto_control.utils.je_auto_control_exception.exception_tag import mouse_error from je_auto_control.utils.je_auto_control_exception.exception_tag import screen_error +from je_auto_control.utils.je_auto_control_exception.exception_tag import record_queue_error class AutoControlException(Exception): @@ -45,3 +46,10 @@ def __init__(self, image, message=cant_find_image): def __str__(self): return "{%s} cause by: {%s}" % (self.message, self.image) + + +class AutoControlRecordException(AutoControlException): + def __init__(self, message=record_queue_error): + super().__init__(message) + + diff --git a/je_auto_control/windows/listener/win32_keyboard_listener.py b/je_auto_control/windows/listener/win32_keyboard_listener.py index 5c74ac4..37f6d99 100644 --- a/je_auto_control/windows/listener/win32_keyboard_listener.py +++ b/je_auto_control/windows/listener/win32_keyboard_listener.py @@ -50,7 +50,7 @@ def _win32_hook_proc(self, code, w_param, l_param): if self.record_flag is True: # int to hex temp = hex(l_param[0] & 0xFFFFFFFF) - self.record_queue.put(("test_keyboard", temp)) + self.record_queue.put(("keyboard", int(temp, 16))) return user32.CallNextHookEx(self.hooked, code, w_param, l_param) def _get_function_pointer(self, function): @@ -59,10 +59,7 @@ def _get_function_pointer(self, function): def _start_listener(self): pointer = self._get_function_pointer(self._win32_hook_proc) - if self._set_win32_hook(pointer): - print("start listener") - else: - print("failed to start") + self._set_win32_hook(pointer) message = MSG() user32.GetMessageA(byref(message), 0, 0, 0) diff --git a/je_auto_control/windows/listener/win32_mouse_listener.py b/je_auto_control/windows/listener/win32_mouse_listener.py index 1628474..a0826e6 100644 --- a/je_auto_control/windows/listener/win32_mouse_listener.py +++ b/je_auto_control/windows/listener/win32_mouse_listener.py @@ -54,11 +54,14 @@ def _win32_hook_proc(self, code, w_param, l_param): if w_param not in wm_mouse_key_code: return user32.CallNextHookEx(self.hooked, code, w_param, l_param) if w_param == wm_mouse_key_code[0] and self.record_flag is True: - self.record_queue.put(("test_left", position())) + x, y = position() + self.record_queue.put(("mouse_left", x, y)) elif w_param == wm_mouse_key_code[1] and self.record_flag is True: - self.record_queue.put(("test_right", position())) + x, y = position() + self.record_queue.put(("mouse_right", x, y)) elif w_param == wm_mouse_key_code[2] and self.record_flag is True: - self.record_queue.put(("test_middle", position())) + x, y = position() + self.record_queue.put(("mouse_middle", x, y)) return user32.CallNextHookEx(self.hooked, code, w_param, l_param) def _get_function_pointer(self, function): @@ -67,10 +70,7 @@ def _get_function_pointer(self, function): def _start_listener(self): pointer = self._get_function_pointer(self._win32_hook_proc) - if self._set_win32_hook(pointer): - print("start listener") - else: - print("failed to start") + self._set_win32_hook(pointer) message = MSG() user32.GetMessageA(byref(message), 0, 0, 0) diff --git a/je_auto_control/windows/mouse/win32_ctype_mouse_control.py b/je_auto_control/windows/mouse/win32_ctype_mouse_control.py index 52028a9..090b1a5 100644 --- a/je_auto_control/windows/mouse/win32_ctype_mouse_control.py +++ b/je_auto_control/windows/mouse/win32_ctype_mouse_control.py @@ -86,10 +86,14 @@ def release_mouse(release_button): ctypes.sizeof(Input)) -def click_mouse(mouse_keycode): +def click_mouse(mouse_keycode, x=None, y=None): """ :param mouse_keycode which mouse keycode we want to click + :param x mouse x position + :param y mouse y position """ + if x and y is not None: + set_position(x, y) press_mouse(mouse_keycode) release_mouse(mouse_keycode) diff --git a/je_auto_control/windows/record/__init__.py b/je_auto_control/windows/record/__init__.py index e69de29..e7f688a 100644 --- a/je_auto_control/windows/record/__init__.py +++ b/je_auto_control/windows/record/__init__.py @@ -0,0 +1 @@ +from je_auto_control.windows.record import * diff --git a/je_auto_control/windows/record/win32_record.py b/je_auto_control/windows/record/win32_record.py new file mode 100644 index 0000000..a5fea94 --- /dev/null +++ b/je_auto_control/windows/record/win32_record.py @@ -0,0 +1,64 @@ +import sys + +if sys.platform not in ["win32", "cygwin", "msys"]: + raise Exception("should be only loaded on windows") + +from je_auto_control.windows.listener.win32_keyboard_listener import Win32KeyboardListener +from je_auto_control.windows.listener.win32_mouse_listener import Win32MouseListener + +from je_auto_control.utils.je_auto_control_exception.exceptions import AutoControlRecordException + +from queue import Queue + + +class Win32Recorder(object): + + def __init__(self): + self.mouse_record_listener = None + self.keyboard_record_listener = None + self.record_queue = None + self.result_queue = None + + def record(self): + self.mouse_record_listener = Win32MouseListener() + self.keyboard_record_listener = Win32KeyboardListener() + self.record_queue = Queue() + self.mouse_record_listener.record(self.record_queue) + self.keyboard_record_listener.record(self.record_queue) + + def stop_record(self): + self.result_queue =self.mouse_record_listener.stop_record() + self.result_queue = self.keyboard_record_listener.stop_record() + self.record_queue = None + return self.result_queue + + def record_mouse(self): + self.mouse_record_listener = Win32MouseListener() + self.record_queue = Queue() + self.mouse_record_listener.record(self.record_queue) + + def stop_record_mouse(self): + self.result_queue = self.mouse_record_listener.stop_record() + self.record_queue = None + return self.result_queue + + def record_keyboard(self): + self.keyboard_record_listener = Win32KeyboardListener() + self.record_queue = Queue() + self.keyboard_record_listener.record(record_queue) + + def stop_record_keyboard(self): + self.result_queue = self.keyboard_record_listener.stop_record() + self.record_queue = None + return self.result_queue + + +win32_recorder = Win32Recorder() + +if __name__ == "__main__": + win32_recorder = Win32Recorder() + win32_recorder.record() + from time import sleep + sleep(10) + for i in win32_recorder.stop_record().queue: + print(i) diff --git a/je_auto_control/wrapper/auto_control_keyboard.py b/je_auto_control/wrapper/auto_control_keyboard.py index f37893f..bb46f40 100644 --- a/je_auto_control/wrapper/auto_control_keyboard.py +++ b/je_auto_control/wrapper/auto_control_keyboard.py @@ -4,7 +4,7 @@ from je_auto_control.utils.je_auto_control_exception.exceptions import AutoControlCantFindKeyException from je_auto_control.utils.je_auto_control_exception.exceptions import AutoControlKeyboardException from je_auto_control.wrapper.platform_wrapper import keyboard -from je_auto_control.wrapper.platform_wrapper import keyboard_listener +from je_auto_control.wrapper.platform_wrapper import keyboard_check from je_auto_control.wrapper.platform_wrapper import keys_table @@ -13,10 +13,11 @@ def press_key(keycode, is_shift=False): :param keycode which keycode we want to press :param is_shift shift is press? """ - try: - keycode = keys_table.get(keycode) - except Exception: - raise AutoControlCantFindKeyException(exception_tag.table_cant_find_key) + if type(keycode) is not int: + try: + keycode = keys_table.get(keycode) + except Exception: + raise AutoControlCantFindKeyException(exception_tag.table_cant_find_key) try: if sys.platform in ["win32", "cygwin", "msys", "linux", "linux2"]: keyboard.press_key(keycode) @@ -31,10 +32,11 @@ def release_key(keycode, is_shift=False): :param keycode which keycode we want to release :param is_shift shift is press? """ - try: - keycode = keys_table.get(keycode) - except Exception: - raise AutoControlCantFindKeyException(exception_tag.table_cant_find_key) + if type(keycode) is not int: + try: + keycode = keys_table.get(keycode) + except Exception: + raise AutoControlCantFindKeyException(exception_tag.table_cant_find_key) try: if sys.platform in ["win32", "cygwin", "msys", "linux", "linux2"]: keyboard.release_key(keycode) @@ -64,7 +66,7 @@ def check_key_is_press(keycode): get_key_code = keycode else: get_key_code = keys_table.get(keycode) - return keyboard_listener.check_key_is_press(keycode=get_key_code) + return keyboard_check.check_key_is_press(keycode=get_key_code) def write(write_string, is_shift=False): diff --git a/je_auto_control/wrapper/auto_control_mouse.py b/je_auto_control/wrapper/auto_control_mouse.py index 5c8458b..32926e8 100644 --- a/je_auto_control/wrapper/auto_control_mouse.py +++ b/je_auto_control/wrapper/auto_control_mouse.py @@ -100,10 +100,7 @@ def click_mouse(mouse_keycode, x=None, y=None): except Exception: raise AutoControlMouseException(exception_tag.mouse_get_position) try: - if sys.platform in ["win32", "cygwin", "msys", "linux", "linux2"]: - mouse.click_mouse(mouse_keycode) - elif sys.platform in ["darwin"]: - mouse.click_mouse(x, y, mouse_keycode) + mouse.click_mouse(mouse_keycode, x, y) except Exception: raise AutoControlMouseException(exception_tag.mouse_click_mouse) diff --git a/je_auto_control/wrapper/auto_control_record.py b/je_auto_control/wrapper/auto_control_record.py new file mode 100644 index 0000000..9263a11 --- /dev/null +++ b/je_auto_control/wrapper/auto_control_record.py @@ -0,0 +1,59 @@ +from je_auto_control.utils.je_auto_control_exception.exceptions import AutoControlRecordException +from je_auto_control.utils.je_auto_control_exception.exception_tag import record_not_found_action_error +from je_auto_control.wrapper.auto_control_mouse import click_mouse +from je_auto_control.wrapper.auto_control_keyboard import type_key +from je_auto_control.wrapper.platform_wrapper import recorder + +event_dict = {"mouse_left": "click_mouse", "mouse_right": "click_mouse", "mouse_middle": "click_mouse", "keyboard": "type_key"} + + +def record_mouse(): + recorder.record_mouse() + + +def stop_record_mouse(): + action_queue = recorder.stop_record_mouse() + if action_queue is None: + raise AutoControlRecordException + for mouse_action in action_queue.queue: + print(mouse_action) + click_mouse(mouse_action[0], mouse_action[1], mouse_action[2]) + + +def record_keyboard(): + recorder.record_keyboard() + + +def stop_record_keyboard(): + action_queue = recorder.stop_record_keyboard() + if action_queue is None: + raise AutoControlRecordException + for keyboard_action in action_queue.queue: + print(keyboard_action) + type_key(keyboard_action[1]) + + +def record(): + recorder.record() + + +def stop_record(): + action_queue = recorder.stop_record() + if action_queue is None: + raise AutoControlRecordException + for action in action_queue.queue: + if event_dict.get(action[0]) == "click_mouse": + click_mouse(action[0], action[1], action[2]) + elif event_dict.get(action[0]) == "type_key": + type_key(action[1]) + else: + raise AutoControlRecordException(record_not_found_action_error) + + + +if __name__ == "__main__": + record() + from time import sleep + sleep(10) + stop_record() + sleep(3) diff --git a/je_auto_control/wrapper/platform_wrapper.py b/je_auto_control/wrapper/platform_wrapper.py index d199f56..7834887 100644 --- a/je_auto_control/wrapper/platform_wrapper.py +++ b/je_auto_control/wrapper/platform_wrapper.py @@ -178,6 +178,7 @@ from je_auto_control.windows.mouse.win32_ctype_mouse_control import win32_mouse_x1 from je_auto_control.windows.mouse.win32_ctype_mouse_control import win32_mouse_x2 from je_auto_control.windows.screen import win32_screen + from je_auto_control.windows.record.win32_record import win32_recorder elif sys.platform in ["darwin"]: from je_auto_control.osx.core.utils.osx_vk import osx_key_a, osx_key_A @@ -282,7 +283,7 @@ from je_auto_control.osx.mouse import osx_mouse from je_auto_control.osx.screen import osx_screen from je_auto_control.osx.keyboard import osx_keyboard - from je_auto_control.osx.keyboard import osx_keyboard_listener + from je_auto_control.osx.keyboard import osx_keyboard_check elif sys.platform in ["linux", "linux2"]: from je_auto_control.linux_with_x11.core.utils.x11_linux_vk import x11_linux_key_backspace @@ -477,6 +478,7 @@ from je_auto_control.linux_with_x11.listener import x11_linux_listener from je_auto_control.linux_with_x11.mouse import x11_linux_mouse_control from je_auto_control.linux_with_x11.screen import x11_linux_screen + from je_auto_control.linux_with_x11.record.x11_linux_record import x11_linux_recoder else: raise AutoControlException("unknown operating system") @@ -485,9 +487,10 @@ mouse_table = None special_table = None keyboard = None -keyboard_listener = None +keyboard_check = None mouse = None screen = None +recorder = None if sys.platform in ["win32", "cygwin", "msys"]: @@ -693,9 +696,13 @@ "mouse_x2": win32_mouse_x2 } keyboard = win32_ctype_keyboard_control - keyboard_listener = win32_keyboard_check + keyboard_check = win32_keyboard_check mouse = win32_ctype_mouse_control screen = win32_screen + recorder = win32_recorder + + if None in [keys_table, mouse_table, keyboard_check, keyboard, mouse, screen, recorder]: + raise AutoControlException("Can't init auto control") elif sys.platform in ["darwin"]: @@ -853,9 +860,11 @@ "mouse_right": osx_mouse_right, } keyboard = osx_keyboard - keyboard_listener = osx_keyboard_listener + keyboard_check = osx_keyboard_check mouse = osx_mouse screen = osx_screen + if None in [keys_table, mouse_table, keyboard_check, keyboard, mouse, screen]: + raise AutoControlException("Can't init auto control") elif sys.platform in ["linux", "linux2"]: @@ -1054,10 +1063,11 @@ "scroll_right": x11_linux_scroll_direction_right } keyboard = x11_linux_keyboard_control - keyboard_listener = x11_linux_listener + keyboard_check = x11_linux_listener mouse = x11_linux_mouse_control screen = x11_linux_screen - if None in [keys_table, mouse_table, special_table, keyboard, mouse, screen]: + recorder = x11_linux_recoder + if None in [keys_table, mouse_table, special_table, keyboard, mouse, screen, recorder]: raise AutoControlException("Can't init auto control") if None in [keys_table, mouse_table, keyboard, mouse, screen]: diff --git a/test/platform_independent/test/test_record.py b/test/platform_independent/test/test_record.py new file mode 100644 index 0000000..e69de29