AutoMonkey 0.4.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- automonkey/__init__.py +37 -0
- automonkey/ai/__init__.py +54 -0
- automonkey/ai/__main__.py +76 -0
- automonkey/ai/mcp_launch.py +62 -0
- automonkey/ai/mcp_server.py +114 -0
- automonkey/ai/ocr.py +149 -0
- automonkey/ai/screen.py +202 -0
- automonkey/ai/script.py +190 -0
- automonkey/ai/windows.py +185 -0
- automonkey/app_funcs.py +201 -0
- automonkey/atspi_funcs.py +1093 -0
- automonkey/automonkey.py +300 -0
- automonkey/constants.py +120 -0
- automonkey/exceptions.py +16 -0
- automonkey/img_funcs.py +301 -0
- automonkey/key_funcs.py +279 -0
- automonkey/mouse_funcs.py +37 -0
- automonkey/mouse_tracker.py +133 -0
- automonkey/pywinauto_funcs.py +343 -0
- automonkey/utils.py +169 -0
- automonkey-0.4.1.dist-info/METADATA +517 -0
- automonkey-0.4.1.dist-info/RECORD +27 -0
- automonkey-0.4.1.dist-info/WHEEL +5 -0
- automonkey-0.4.1.dist-info/entry_points.txt +3 -0
- automonkey-0.4.1.dist-info/licenses/AUTHORS.rst +13 -0
- automonkey-0.4.1.dist-info/licenses/LICENSE +33 -0
- automonkey-0.4.1.dist-info/top_level.txt +1 -0
automonkey/automonkey.py
ADDED
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
"""Python Automation using Mouse and Keyboard, for the masses
|
|
2
|
+
"""
|
|
3
|
+
from time import sleep
|
|
4
|
+
from sys import exit as end
|
|
5
|
+
|
|
6
|
+
from sys import platform
|
|
7
|
+
|
|
8
|
+
if platform == "win32":
|
|
9
|
+
from os import startfile # It is used
|
|
10
|
+
elif platform == "linux":
|
|
11
|
+
from subprocess import call
|
|
12
|
+
def startfile(file):
|
|
13
|
+
call(["xdg-open", file])
|
|
14
|
+
|
|
15
|
+
from clipboard import paste
|
|
16
|
+
|
|
17
|
+
from pyautogui import click # It is used
|
|
18
|
+
from pyautogui import moveTo # It is used
|
|
19
|
+
from pyautogui import mouseUp # It is used
|
|
20
|
+
from pyautogui import confirm
|
|
21
|
+
from pyautogui import mouseDown # It is used
|
|
22
|
+
from pyautogui import locateOnScreen
|
|
23
|
+
from pyautogui import scroll as scrollup # It is used
|
|
24
|
+
from pyautogui import hscroll as scrollright # It is used
|
|
25
|
+
from pyautogui import leftClick as leftclick # It is used
|
|
26
|
+
from pyautogui import rightClick as rightclick # It is used
|
|
27
|
+
from pyautogui import middleClick as middleclick # It is used
|
|
28
|
+
from pyautogui import doubleClick as doubleclick # It is used
|
|
29
|
+
from pyautogui import tripleClick as tripleclick # It is used
|
|
30
|
+
from keyboard import send as keys3 # works mostly on windows - TODO: Check difference to below
|
|
31
|
+
from keyboard import press_and_release as keys4 # works mostly on windows
|
|
32
|
+
|
|
33
|
+
from screeninfo import get_monitors
|
|
34
|
+
|
|
35
|
+
from .constants import MOUSE_ACTIONS
|
|
36
|
+
from .constants import WAIT_ACTIONS
|
|
37
|
+
from .constants import KEYBOARD_ACTIONS
|
|
38
|
+
from .constants import APPS_ACTIONS
|
|
39
|
+
from .constants import IMG_ACTIONS
|
|
40
|
+
from .constants import CONTROL_ACTIONS
|
|
41
|
+
from .constants import COMMON_APPS
|
|
42
|
+
|
|
43
|
+
from .exceptions import AutoMonkeyNoAction
|
|
44
|
+
from .exceptions import AutoMonkeyNoTarget
|
|
45
|
+
|
|
46
|
+
from .mouse_tracker import track_mouse
|
|
47
|
+
from .mouse_tracker import PositionTracker
|
|
48
|
+
|
|
49
|
+
from .key_funcs import write # keyboard-layout aware
|
|
50
|
+
from .key_funcs import press as keys # this normally is to be used for same key left, left, left
|
|
51
|
+
from .key_funcs import hotkey as keys2 # this is best solution, pass list to be unpacked with *list
|
|
52
|
+
|
|
53
|
+
if platform == "win32":
|
|
54
|
+
from .app_funcs import open_app
|
|
55
|
+
from .app_funcs import minimize
|
|
56
|
+
from .app_funcs import maximize
|
|
57
|
+
from .app_funcs import close
|
|
58
|
+
from .app_funcs import restore
|
|
59
|
+
from .app_funcs import focus
|
|
60
|
+
from .app_funcs import msoffice_replace
|
|
61
|
+
from .app_funcs import copy
|
|
62
|
+
|
|
63
|
+
from .mouse_funcs import movedown
|
|
64
|
+
from .mouse_funcs import moveleft
|
|
65
|
+
from .mouse_funcs import moveright
|
|
66
|
+
from .mouse_funcs import moveup
|
|
67
|
+
|
|
68
|
+
from .img_funcs import _add_ext
|
|
69
|
+
from .img_funcs import is_on_screen
|
|
70
|
+
from .img_funcs import get_center
|
|
71
|
+
from .img_funcs import diagonal_point
|
|
72
|
+
|
|
73
|
+
from .utils import waitwhile
|
|
74
|
+
from .utils import waituntil
|
|
75
|
+
from .utils import pastetext
|
|
76
|
+
from .utils import copy_from
|
|
77
|
+
from .utils import scrolldown
|
|
78
|
+
from .utils import scrollleft
|
|
79
|
+
from .utils import copy_from_to
|
|
80
|
+
|
|
81
|
+
if platform == "win32":
|
|
82
|
+
from .pywinauto_funcs import get_window
|
|
83
|
+
from .pywinauto_funcs import get_control
|
|
84
|
+
from .pywinauto_funcs import start_app
|
|
85
|
+
from .pywinauto_funcs import click_control
|
|
86
|
+
from .pywinauto_funcs import double_click_control
|
|
87
|
+
from .pywinauto_funcs import right_click_control
|
|
88
|
+
from .pywinauto_funcs import type_in_control
|
|
89
|
+
from .pywinauto_funcs import set_control_text
|
|
90
|
+
from .pywinauto_funcs import get_control_text
|
|
91
|
+
from .pywinauto_funcs import select_menu
|
|
92
|
+
from .pywinauto_funcs import select_item
|
|
93
|
+
from .pywinauto_funcs import check_control
|
|
94
|
+
from .pywinauto_funcs import uncheck_control
|
|
95
|
+
from .pywinauto_funcs import wait_control
|
|
96
|
+
from .pywinauto_funcs import control_exists
|
|
97
|
+
from .pywinauto_funcs import list_controls
|
|
98
|
+
else: # linux: real AT-SPI backend; macOS: importable, raises NotImplementedError when used
|
|
99
|
+
from .atspi_funcs import get_window
|
|
100
|
+
from .atspi_funcs import get_control
|
|
101
|
+
from .atspi_funcs import start_app
|
|
102
|
+
from .atspi_funcs import click_control
|
|
103
|
+
from .atspi_funcs import double_click_control
|
|
104
|
+
from .atspi_funcs import right_click_control
|
|
105
|
+
from .atspi_funcs import type_in_control
|
|
106
|
+
from .atspi_funcs import set_control_text
|
|
107
|
+
from .atspi_funcs import get_control_text
|
|
108
|
+
from .atspi_funcs import select_menu
|
|
109
|
+
from .atspi_funcs import select_item
|
|
110
|
+
from .atspi_funcs import check_control
|
|
111
|
+
from .atspi_funcs import uncheck_control
|
|
112
|
+
from .atspi_funcs import wait_control
|
|
113
|
+
from .atspi_funcs import control_exists
|
|
114
|
+
from .atspi_funcs import list_controls
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
ALL_ACTIONS = MOUSE_ACTIONS + KEYBOARD_ACTIONS + WAIT_ACTIONS + APPS_ACTIONS + IMG_ACTIONS + CONTROL_ACTIONS
|
|
118
|
+
|
|
119
|
+
def _wait_for_target(target: any, skip: bool = False):
|
|
120
|
+
"""Wait for a target to be available"""
|
|
121
|
+
slept = 0
|
|
122
|
+
while not is_on_screen(target) and not skip:
|
|
123
|
+
sleep(0.1)
|
|
124
|
+
slept += 0.1
|
|
125
|
+
if int(slept) == 30: # For production make it 300
|
|
126
|
+
stop = confirm("Next target was not found for 5 minutes.\
|
|
127
|
+
Would you like to continue or stop?",
|
|
128
|
+
"Continue?",
|
|
129
|
+
["Continue", "Stop"])
|
|
130
|
+
if stop == "Stop":
|
|
131
|
+
end()
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def _prepare_step(raw_step: dict) -> dict:
|
|
135
|
+
"""Transform the raw step into a step that can be used by the script
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
raw_step (dict): The raw step from the json file
|
|
139
|
+
|
|
140
|
+
Raises:
|
|
141
|
+
AutoMonkeyNoAction: If the action is not supported
|
|
142
|
+
AutoMonkeyNoTarget: If the target is not supported
|
|
143
|
+
|
|
144
|
+
Returns:
|
|
145
|
+
dict: The step that can be used by the script
|
|
146
|
+
"""
|
|
147
|
+
step = dict(
|
|
148
|
+
action=None,
|
|
149
|
+
target=None,
|
|
150
|
+
skip=False,
|
|
151
|
+
wait=0,
|
|
152
|
+
confidence=0.9,
|
|
153
|
+
v_offset=0,
|
|
154
|
+
h_offset=0,
|
|
155
|
+
offset=None,
|
|
156
|
+
monitor=1,
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
for arg_pair in raw_step.items():
|
|
160
|
+
step["action"] = arg_pair[0] if arg_pair[0] in ALL_ACTIONS else step["action"]
|
|
161
|
+
step["target"] = arg_pair[1] if arg_pair[0] in ALL_ACTIONS else step["target"]
|
|
162
|
+
step["skip"] = bool(arg_pair[1]) if arg_pair[0] == 'skip' else step["skip"]
|
|
163
|
+
step["wait"] = float(arg_pair[1]) if arg_pair[0] == 'wait' else step["wait"]
|
|
164
|
+
step["confidence"] = float(arg_pair[1]) if arg_pair[0] == 'confidence' else step["confidence"]
|
|
165
|
+
step["v_offset"] = int(arg_pair[1]) if arg_pair[0] == 'v_offset' else step["v_offset"]
|
|
166
|
+
step["h_offset"] = int(arg_pair[1]) if arg_pair[0] == 'h_offset' else step["h_offset"]
|
|
167
|
+
step["offset"] = str(arg_pair[1]) if arg_pair[0] == 'offset' else step["offset"]
|
|
168
|
+
step["monitor"] = arg_pair[1] if arg_pair[0] == 'monitor' else step["monitor"]
|
|
169
|
+
|
|
170
|
+
if step["action"] not in ALL_ACTIONS:
|
|
171
|
+
raise AutoMonkeyNoAction(step["action"])
|
|
172
|
+
|
|
173
|
+
if step["target"] is None:
|
|
174
|
+
raise AutoMonkeyNoTarget(step["target"])
|
|
175
|
+
return step
|
|
176
|
+
|
|
177
|
+
def __run_1(step: dict):
|
|
178
|
+
step["target"] = _add_ext(step["target"])
|
|
179
|
+
_wait_for_target(step["target"], step["skip"])
|
|
180
|
+
|
|
181
|
+
bullseye = locateOnScreen(step["target"], confidence=step["confidence"])
|
|
182
|
+
bullseye = get_center(bullseye)
|
|
183
|
+
bullseye = diagonal_point(bullseye, step["h_offset"], step["v_offset"])
|
|
184
|
+
if step["offset"] not in ("", None):
|
|
185
|
+
globals()["_offset_clicks"](bullseye, step["target"], step["offset"], step["action"])
|
|
186
|
+
else:
|
|
187
|
+
globals()[step["action"]](bullseye)
|
|
188
|
+
|
|
189
|
+
def __run_control(step: dict):
|
|
190
|
+
if isinstance(step["target"], dict):
|
|
191
|
+
globals()[step["action"]](**step["target"])
|
|
192
|
+
elif isinstance(step["target"], (tuple, list)):
|
|
193
|
+
globals()[step["action"]](*step["target"])
|
|
194
|
+
else:
|
|
195
|
+
globals()[step["action"]](step["target"])
|
|
196
|
+
|
|
197
|
+
def __run_2(step: dict):
|
|
198
|
+
if step["action"] in CONTROL_ACTIONS:
|
|
199
|
+
__run_control(step)
|
|
200
|
+
elif step["action"] in ("keys2", "msoffice_replace"):
|
|
201
|
+
globals()[step["action"]](*step["target"])
|
|
202
|
+
elif step["action"] == "paste":
|
|
203
|
+
pastetext(paste())
|
|
204
|
+
elif step["action"] == "open_app":
|
|
205
|
+
__run_3(step)
|
|
206
|
+
else:
|
|
207
|
+
globals()[step["action"]](step["target"])
|
|
208
|
+
|
|
209
|
+
def __run_3(step: dict):
|
|
210
|
+
if step["target"].lower() in COMMON_APPS:
|
|
211
|
+
globals()[step["action"]](COMMON_APPS[step["target"].lower()])
|
|
212
|
+
else:
|
|
213
|
+
globals()[step["action"]](step["target"])
|
|
214
|
+
|
|
215
|
+
def __monitors():
|
|
216
|
+
monitors = {}
|
|
217
|
+
for _, mon in enumerate(sorted([(mon.x, mon.y) for mon in get_monitors()], key=lambda tup: tup[0])):
|
|
218
|
+
monitors[_] = (mon[0], mon[1])
|
|
219
|
+
return monitors
|
|
220
|
+
|
|
221
|
+
def __target_1(step: dict):
|
|
222
|
+
step["target"] = step["target"].split("+") if step["action"] in ("keys", "keys2") else step["target"]
|
|
223
|
+
return step
|
|
224
|
+
|
|
225
|
+
def __target_2(step: dict):
|
|
226
|
+
monitors = __monitors()
|
|
227
|
+
try:
|
|
228
|
+
if step["action"] in ("keys", "keys2") and isinstance(step["target"], tuple):
|
|
229
|
+
step["target"] = (step["target"][0] + monitors[step["monitor"] - 1][0], step["target"][1]) if step["target"][0] < monitors[1][0] else step["target"]
|
|
230
|
+
return step
|
|
231
|
+
except IndexError:
|
|
232
|
+
pass
|
|
233
|
+
except KeyError:
|
|
234
|
+
pass
|
|
235
|
+
return step
|
|
236
|
+
|
|
237
|
+
def __run_1_cond(step: dict):
|
|
238
|
+
return step["action"] in MOUSE_ACTIONS and not isinstance(step["target"], tuple) and not isinstance(step["target"], int)
|
|
239
|
+
|
|
240
|
+
def __debug_1(debug: bool, step: dict):
|
|
241
|
+
if debug:
|
|
242
|
+
print(step)
|
|
243
|
+
|
|
244
|
+
def chain(*steps: dict, debug=False):
|
|
245
|
+
"""Chain together a series of automation steps
|
|
246
|
+
|
|
247
|
+
Args:
|
|
248
|
+
*steps (dict): Unlimitted number of automation steps as dictionaries.
|
|
249
|
+
Each automation step should be a dictionary with 1 or more pairs:
|
|
250
|
+
- First pair is the Action - Target pair. The only mandatory pair.
|
|
251
|
+
Example: dict(click: "image.jpg") or {"click": "image.jpg"}
|
|
252
|
+
- Next possible pairs are optional:
|
|
253
|
+
* skip (True/False) - optional. If True, the step will be skipped if the target is not found.
|
|
254
|
+
* wait - Seconds to wait after performing the action. Defaults to zero.
|
|
255
|
+
* confidence - optional. Used only for actions on images. Confidence on locating the image.
|
|
256
|
+
Defaults to 0.9
|
|
257
|
+
* v_offset - optional. Vertical offset from the center of the target.
|
|
258
|
+
* h_offset - optional. Horizontal offset from the center of the target.
|
|
259
|
+
* offset - optional. Offset from the center of the target. Overrides v_offset and h_offset.
|
|
260
|
+
* monitor - optional. Monitor number to perform the action on. Defaults to 1.
|
|
261
|
+
|
|
262
|
+
Example of steps:
|
|
263
|
+
chain(
|
|
264
|
+
dict(write="this string", wait=0.5),
|
|
265
|
+
dict(write="this other string"),
|
|
266
|
+
dict(click="C:\\Folder1\\Folder2\\image.jpg", wait=2, confidence=0.8),
|
|
267
|
+
debug=True)
|
|
268
|
+
|
|
269
|
+
debug (bool, optional): Debug variable, if True will print each step. Defaults to False.
|
|
270
|
+
|
|
271
|
+
Notes:
|
|
272
|
+
1. To use the scroll functions you have to select the scrollable area first
|
|
273
|
+
2. Horizontal scroll (left, right) is not supported on Windows
|
|
274
|
+
3. write, keys and keys2 work with any keyboard layout and PowerToys key remaps on Windows,
|
|
275
|
+
and write types any character there (German, Chinese, ...). keys3/keys4 are not layout aware.
|
|
276
|
+
4. startfile keeps the file opened only until the end of the chain.
|
|
277
|
+
If you want to keep the file opened you need to perform other operations on it.
|
|
278
|
+
5. When using startfile you are responsible for saving and closing the file.
|
|
279
|
+
6. For the app functions (start, close, minimize, maximize, restore, focus) you need to provide the title of the window.add()
|
|
280
|
+
You can also use regex to match the title.
|
|
281
|
+
7. The control actions (click_control, type_in_control, ...) use pywinauto on Windows
|
|
282
|
+
and AT-SPI on Linux (see pywinauto_for_linux.md; macOS not implemented yet).
|
|
283
|
+
The target is a tuple of arguments (window, control, ...) or a dict of keyword arguments:
|
|
284
|
+
dict(click_control=("Notepad", "File")),
|
|
285
|
+
dict(type_in_control=dict(window="Notepad", control={"control_type": "Document"}, text="hi")),
|
|
286
|
+
|
|
287
|
+
"""
|
|
288
|
+
for _ in steps:
|
|
289
|
+
step = _prepare_step(_)
|
|
290
|
+
__debug_1(debug, step)
|
|
291
|
+
|
|
292
|
+
step = __target_1(step)
|
|
293
|
+
step = __target_2(step)
|
|
294
|
+
|
|
295
|
+
if __run_1_cond(step):
|
|
296
|
+
__run_1(step)
|
|
297
|
+
else:
|
|
298
|
+
__run_2(step)
|
|
299
|
+
|
|
300
|
+
sleep(step["wait"])
|
automonkey/constants.py
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
IMG_EXT = (
|
|
2
|
+
".png",
|
|
3
|
+
".jpg",
|
|
4
|
+
".jpeg",
|
|
5
|
+
".tiff",
|
|
6
|
+
".tif",
|
|
7
|
+
".bmp",
|
|
8
|
+
".gif",
|
|
9
|
+
".pdf",
|
|
10
|
+
".webp",
|
|
11
|
+
".PNG",
|
|
12
|
+
".JPG",
|
|
13
|
+
".JPEG",
|
|
14
|
+
".TIFF",
|
|
15
|
+
".TIF",
|
|
16
|
+
".BMP",
|
|
17
|
+
".GIF",
|
|
18
|
+
".PDF",
|
|
19
|
+
".WEBP"
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
MOUSE_ACTIONS = (
|
|
23
|
+
"click",
|
|
24
|
+
"leftclick",
|
|
25
|
+
"rightclick",
|
|
26
|
+
"doubleclick",
|
|
27
|
+
"tripleclick",
|
|
28
|
+
"scrollup",
|
|
29
|
+
"scrolldown",
|
|
30
|
+
"scrollleft",
|
|
31
|
+
"scrollright",
|
|
32
|
+
"moveup",
|
|
33
|
+
"movedown",
|
|
34
|
+
"moveleft",
|
|
35
|
+
"moveright"
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
WAIT_ACTIONS = (
|
|
39
|
+
"waitwhile",
|
|
40
|
+
"waituntil",
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
KEYBOARD_ACTIONS = (
|
|
44
|
+
"write",
|
|
45
|
+
"pastetext",
|
|
46
|
+
"keys",
|
|
47
|
+
"keys2",
|
|
48
|
+
"keys3",
|
|
49
|
+
"keys4",
|
|
50
|
+
"copy",
|
|
51
|
+
"paste",
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
APPS_ACTIONS = (
|
|
55
|
+
"close",
|
|
56
|
+
"focus",
|
|
57
|
+
"open_app",
|
|
58
|
+
"startfile",
|
|
59
|
+
"minimize",
|
|
60
|
+
"maximize",
|
|
61
|
+
"restore",
|
|
62
|
+
"copy_from",
|
|
63
|
+
"copy_from_to",
|
|
64
|
+
"msoffice_replace",
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
IMG_ACTIONS = (
|
|
68
|
+
"count_img",
|
|
69
|
+
"get_text_from_region",
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
# pywinauto based actions. Target: window title, (window, control, ...) tuple or dict of arguments
|
|
73
|
+
CONTROL_ACTIONS = (
|
|
74
|
+
"start_app",
|
|
75
|
+
"click_control",
|
|
76
|
+
"double_click_control",
|
|
77
|
+
"right_click_control",
|
|
78
|
+
"type_in_control",
|
|
79
|
+
"set_control_text",
|
|
80
|
+
"get_control_text",
|
|
81
|
+
"select_menu",
|
|
82
|
+
"select_item",
|
|
83
|
+
"check_control",
|
|
84
|
+
"uncheck_control",
|
|
85
|
+
"wait_control",
|
|
86
|
+
"list_controls",
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
COMMON_APPS = {
|
|
90
|
+
"edge": "msedge",
|
|
91
|
+
"msedge": "msedge",
|
|
92
|
+
"microsoft edge": "msedge",
|
|
93
|
+
"chrome": "chrome",
|
|
94
|
+
"google chrome": "chrome",
|
|
95
|
+
"firefox": "firefox",
|
|
96
|
+
"mozilla firefox": "firefox",
|
|
97
|
+
"notepad": "notepad",
|
|
98
|
+
"notepad++": "notepad++",
|
|
99
|
+
"excel": "excel",
|
|
100
|
+
"microsoft excel": "excel",
|
|
101
|
+
"word": "word",
|
|
102
|
+
"microsoft word": "word",
|
|
103
|
+
"powerpoint": "powerpoint",
|
|
104
|
+
"microsoft powerpoint": "powerpoint",
|
|
105
|
+
"outlook": "outlook",
|
|
106
|
+
"microsoft outlook": "outlook",
|
|
107
|
+
"onenote": "onenote",
|
|
108
|
+
"microsoft onenote": "onenote",
|
|
109
|
+
"vscode": "code",
|
|
110
|
+
"visual studio code": "code",
|
|
111
|
+
"explorer": "explorer",
|
|
112
|
+
"windows explorer": "explorer",
|
|
113
|
+
"files": "explorer",
|
|
114
|
+
"file explorer": "explorer",
|
|
115
|
+
"cmd": "cmd",
|
|
116
|
+
"command prompt": "cmd",
|
|
117
|
+
"terminal": "cmd",
|
|
118
|
+
"powershell": "powershell",
|
|
119
|
+
"power shell": "powershell",
|
|
120
|
+
}
|
automonkey/exceptions.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
class AutoMonkeyNoAction(Exception):
|
|
2
|
+
"""
|
|
3
|
+
AutoMonkey chain function will raise this Exception if no valid action exists
|
|
4
|
+
in an automation step of the chain sequence.
|
|
5
|
+
"""
|
|
6
|
+
def __init__(self, message):
|
|
7
|
+
super().__init__(f"The provided action is not supported: {message}")
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class AutoMonkeyNoTarget(Exception):
|
|
11
|
+
"""
|
|
12
|
+
AutoMonkey chain function will raise this Exception if no valid target exists
|
|
13
|
+
in an automation step of the chain sequence.
|
|
14
|
+
"""
|
|
15
|
+
def __init__(self, message):
|
|
16
|
+
super().__init__(f"The provided target is not supported: {message}")
|