kotonebot 0.5.0__py3-none-any.whl → 0.7.0__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.
Files changed (107) hide show
  1. kotonebot/__init__.py +39 -39
  2. kotonebot/backend/bot.py +312 -312
  3. kotonebot/backend/color.py +525 -525
  4. kotonebot/backend/context/__init__.py +3 -3
  5. kotonebot/backend/context/context.py +1002 -1002
  6. kotonebot/backend/context/task_action.py +183 -183
  7. kotonebot/backend/core.py +86 -129
  8. kotonebot/backend/debug/entry.py +89 -89
  9. kotonebot/backend/debug/mock.py +78 -78
  10. kotonebot/backend/debug/server.py +222 -222
  11. kotonebot/backend/debug/vars.py +351 -351
  12. kotonebot/backend/dispatch.py +227 -227
  13. kotonebot/backend/flow_controller.py +196 -196
  14. kotonebot/backend/image.py +36 -5
  15. kotonebot/backend/loop.py +222 -208
  16. kotonebot/backend/ocr.py +535 -535
  17. kotonebot/backend/preprocessor.py +103 -103
  18. kotonebot/client/__init__.py +9 -9
  19. kotonebot/client/device.py +369 -529
  20. kotonebot/client/fast_screenshot.py +377 -377
  21. kotonebot/client/host/__init__.py +43 -43
  22. kotonebot/client/host/adb_common.py +101 -107
  23. kotonebot/client/host/custom.py +118 -118
  24. kotonebot/client/host/leidian_host.py +196 -196
  25. kotonebot/client/host/mumu12_host.py +353 -353
  26. kotonebot/client/host/protocol.py +214 -214
  27. kotonebot/client/host/windows_common.py +73 -58
  28. kotonebot/client/implements/__init__.py +65 -70
  29. kotonebot/client/implements/adb.py +89 -89
  30. kotonebot/client/implements/nemu_ipc/__init__.py +11 -11
  31. kotonebot/client/implements/nemu_ipc/external_renderer_ipc.py +284 -284
  32. kotonebot/client/implements/nemu_ipc/nemu_ipc.py +327 -327
  33. kotonebot/client/implements/remote_windows.py +188 -188
  34. kotonebot/client/implements/uiautomator2.py +85 -85
  35. kotonebot/client/implements/windows/__init__.py +1 -0
  36. kotonebot/client/implements/windows/print_window.py +133 -0
  37. kotonebot/client/implements/windows/send_message.py +324 -0
  38. kotonebot/client/implements/{windows.py → windows/windows.py} +175 -176
  39. kotonebot/client/protocol.py +69 -69
  40. kotonebot/client/registration.py +24 -24
  41. kotonebot/client/scaler.py +467 -0
  42. kotonebot/config/base_config.py +103 -96
  43. kotonebot/config/config.py +61 -0
  44. kotonebot/config/manager.py +36 -36
  45. kotonebot/core/__init__.py +13 -0
  46. kotonebot/core/entities/base.py +182 -0
  47. kotonebot/core/entities/compound.py +75 -0
  48. kotonebot/core/entities/ocr.py +117 -0
  49. kotonebot/core/entities/template_match.py +198 -0
  50. kotonebot/devtools/__init__.py +42 -0
  51. kotonebot/devtools/cli/__init__.py +6 -0
  52. kotonebot/devtools/cli/main.py +53 -0
  53. kotonebot/{tools → devtools}/mirror.py +354 -354
  54. kotonebot/devtools/project/project.py +41 -0
  55. kotonebot/devtools/project/scanner.py +202 -0
  56. kotonebot/devtools/project/schema.py +99 -0
  57. kotonebot/devtools/resgen/__init__.py +42 -0
  58. kotonebot/devtools/resgen/codegen.py +331 -0
  59. kotonebot/devtools/resgen/core.py +94 -0
  60. kotonebot/devtools/resgen/parsers.py +360 -0
  61. kotonebot/devtools/resgen/utils.py +158 -0
  62. kotonebot/devtools/resgen/validation.py +115 -0
  63. kotonebot/devtools/web/dist/assets/bootstrap-icons-BOrJxbIo.woff +0 -0
  64. kotonebot/devtools/web/dist/assets/bootstrap-icons-BtvjY1KL.woff2 +0 -0
  65. kotonebot/devtools/web/dist/assets/ext-language_tools-CD021WJ2.js +2577 -0
  66. kotonebot/devtools/web/dist/assets/index-B_m5f2LF.js +2836 -0
  67. kotonebot/devtools/web/dist/assets/index-BlEDyGGa.css +9 -0
  68. kotonebot/devtools/web/dist/assets/language-client-C9muzqaq.js +128 -0
  69. kotonebot/devtools/web/dist/assets/mode-python-CtHp76XS.js +476 -0
  70. kotonebot/devtools/web/dist/icons/symbol-class.svg +3 -0
  71. kotonebot/devtools/web/dist/icons/symbol-file.svg +3 -0
  72. kotonebot/devtools/web/dist/icons/symbol-method.svg +3 -0
  73. kotonebot/devtools/web/dist/index.html +25 -0
  74. kotonebot/devtools/web/server/__init__.py +0 -0
  75. kotonebot/devtools/web/server/rest_api.py +217 -0
  76. kotonebot/devtools/web/server/server.py +85 -0
  77. kotonebot/errors.py +76 -76
  78. kotonebot/interop/win/__init__.py +13 -9
  79. kotonebot/interop/win/_mouse.py +310 -310
  80. kotonebot/interop/win/message_box.py +313 -313
  81. kotonebot/interop/win/reg.py +37 -37
  82. kotonebot/interop/win/shake_mouse.py +224 -0
  83. kotonebot/interop/win/shortcut.py +43 -43
  84. kotonebot/interop/win/task_dialog.py +513 -513
  85. kotonebot/interop/win/window.py +89 -0
  86. kotonebot/logging/__init__.py +2 -2
  87. kotonebot/logging/log.py +17 -17
  88. kotonebot/primitives/__init__.py +19 -17
  89. kotonebot/primitives/geometry.py +1067 -862
  90. kotonebot/primitives/visual.py +143 -63
  91. kotonebot/ui/file_host/sensio.py +36 -36
  92. kotonebot/ui/file_host/tmp_send.py +54 -54
  93. kotonebot/ui/pushkit/__init__.py +3 -3
  94. kotonebot/ui/pushkit/image_host.py +88 -88
  95. kotonebot/ui/pushkit/protocol.py +13 -13
  96. kotonebot/ui/pushkit/wxpusher.py +54 -54
  97. kotonebot/ui/user.py +148 -148
  98. kotonebot/util.py +436 -436
  99. {kotonebot-0.5.0.dist-info → kotonebot-0.7.0.dist-info}/METADATA +84 -82
  100. kotonebot-0.7.0.dist-info/RECORD +109 -0
  101. {kotonebot-0.5.0.dist-info → kotonebot-0.7.0.dist-info}/WHEEL +1 -1
  102. kotonebot-0.7.0.dist-info/entry_points.txt +2 -0
  103. {kotonebot-0.5.0.dist-info → kotonebot-0.7.0.dist-info}/licenses/LICENSE +673 -673
  104. kotonebot/client/implements/adb_raw.py +0 -163
  105. kotonebot-0.5.0.dist-info/RECORD +0 -71
  106. /kotonebot/{tools → devtools/project}/__init__.py +0 -0
  107. {kotonebot-0.5.0.dist-info → kotonebot-0.7.0.dist-info}/top_level.txt +0 -0
@@ -1,228 +1,228 @@
1
- import time
2
- import logging
3
- from dataclasses import dataclass
4
- from typing import Any, Callable, Literal
5
-
6
- from dataclasses import dataclass
7
-
8
- from kotonebot.backend.ocr import StringMatchFunction
9
- from kotonebot.primitives import Rect, is_rect
10
-
11
- from .core import Image
12
-
13
- logger = logging.getLogger(__name__)
14
-
15
- @dataclass
16
- class ClickParams:
17
- finish: bool = False
18
- log: str | None = None
19
-
20
- class ClickCenter:
21
- def __init__(self, sd: 'SimpleDispatcher', target: Image | str | StringMatchFunction | Literal['center'], *, params: ClickParams = ClickParams()):
22
- self.target = target
23
- self.params = params
24
- self.sd = sd
25
-
26
- def __call__(self):
27
- from kotonebot import device
28
- if self.params.log:
29
- self.sd.logger.info(self.params.log)
30
- device.click_center()
31
- if self.params.finish:
32
- self.sd.finished = True
33
-
34
- class ClickImage:
35
- def __init__(self, sd: 'SimpleDispatcher', image: Image, *, params: ClickParams = ClickParams()):
36
- self.image = image
37
- self.params = params
38
- self.sd = sd
39
-
40
- def __call__(self):
41
- from kotonebot import device, image
42
- if image.find(self.image):
43
- if self.params.log:
44
- self.sd.logger.info(self.params.log)
45
- device.click()
46
- if self.params.finish:
47
- self.sd.finished = True
48
-
49
- class ClickImageAny:
50
- def __init__(self, sd: 'SimpleDispatcher', images: list[Image], params: ClickParams = ClickParams()):
51
- self.images = images
52
- self.params = params
53
- self.sd = sd
54
-
55
- def __call__(self):
56
- from kotonebot import device, image
57
- if image.find_multi(self.images):
58
- if self.params.log:
59
- self.sd.logger.info(self.params.log)
60
- device.click()
61
- if self.params.finish:
62
- self.sd.finished = True
63
-
64
- class ClickText:
65
- def __init__(
66
- self,
67
- sd: 'SimpleDispatcher',
68
- text: str | StringMatchFunction,
69
- params: ClickParams = ClickParams()
70
- ):
71
- self.text = text
72
- self.params = params
73
- self.sd = sd
74
-
75
- def __call__(self):
76
- from kotonebot import device, ocr
77
- if ocr.find(self.text):
78
- if self.params.log:
79
- self.sd.logger.info(self.params.log)
80
- device.click()
81
- if self.params.finish:
82
- self.sd.finished = True
83
-
84
- class ClickRect:
85
- def __init__(self, sd: 'SimpleDispatcher', rect: Rect, *, params: ClickParams = ClickParams()):
86
- self.rect = rect
87
- self.params = params
88
- self.sd = sd
89
-
90
- def __call__(self):
91
- from kotonebot import device
92
- if device.click(self.rect):
93
- if self.params.log:
94
- self.sd.logger.info(self.params.log)
95
- if self.params.finish:
96
- self.sd.finished = True
97
-
98
- class UntilText:
99
- def __init__(
100
- self,
101
- sd: 'SimpleDispatcher',
102
- text: str | StringMatchFunction,
103
- *,
104
- rect: Rect | None = None,
105
- result: Any | None = None
106
- ):
107
- self.text = text
108
- self.sd = sd
109
- self.rect = rect
110
- self.result = result
111
-
112
- def __call__(self):
113
- from kotonebot import ocr
114
- if ocr.find(self.text, rect=self.rect):
115
- self.sd.finished = True
116
- self.sd.result = self.result
117
-
118
- class UntilImage:
119
- def __init__(
120
- self,
121
- sd: 'SimpleDispatcher',
122
- image: Image,
123
- *,
124
- rect: Rect | None = None,
125
- result: Any | None = None
126
- ):
127
- self.image = image
128
- self.sd = sd
129
- self.rect = rect
130
- self.result = result
131
-
132
- def __call__(self):
133
- from kotonebot import image
134
- if self.rect:
135
- logger.warning(f'UntilImage with rect is deprecated. Use UntilText instead.')
136
- if image.find(self.image):
137
- self.sd.finished = True
138
- self.sd.result = self.result
139
-
140
- class SimpleDispatcher:
141
- def __init__(self, name: str, *, min_interval: float = 0.3):
142
- self.name = name
143
- self.logger = logging.getLogger(f'SimpleDispatcher of {name}')
144
- self.blocks: list[Callable] = []
145
- self.finished: bool = False
146
- self.result: Any | None = None
147
- self.min_interval = min_interval
148
- self.timeout_value: float | None = None
149
- self.timeout_critical: bool = False
150
- self.__last_run_time: float = 0
151
-
152
- def click(
153
- self,
154
- target: Image | StringMatchFunction | Literal['center'] | Rect,
155
- *,
156
- finish: bool = False,
157
- log: str | None = None
158
- ):
159
- params = ClickParams(finish=finish, log=log)
160
- if isinstance(target, Image):
161
- self.blocks.append(ClickImage(self, target, params=params))
162
- elif is_rect(target):
163
- self.blocks.append(ClickRect(self, target, params=params))
164
- elif callable(target):
165
- self.blocks.append(ClickText(self, target, params=params))
166
- elif target == 'center':
167
- self.blocks.append(ClickCenter(self, target='center', params=params))
168
- else:
169
- raise ValueError(f'Invalid target: {target}')
170
- return self
171
-
172
- def click_any(
173
- self,
174
- target: list[Image],
175
- *,
176
- finish: bool = False,
177
- log: str | None = None
178
- ):
179
- params = ClickParams(finish=finish, log=log)
180
- self.blocks.append(ClickImageAny(self, target, params))
181
- return self
182
-
183
- def until(
184
- self,
185
- text: StringMatchFunction | Image,
186
- *,
187
- rect: Rect | None = None,
188
- result: Any | None = None
189
- ):
190
- if isinstance(text, Image):
191
- self.blocks.append(UntilImage(self, text, rect=rect, result=result))
192
- else:
193
- self.blocks.append(UntilText(self, text, rect=rect, result=result))
194
- return self
195
-
196
- def timeout(self, timeout: float, *, critical: bool = False, result: Any | None = None):
197
- self.timeout_value = timeout
198
- self.timeout_critical = critical
199
- self.timeout_result = result
200
- return self
201
-
202
- def run(self):
203
- from kotonebot import device, sleep
204
- while True:
205
- logger.debug(f'Running dispatcher "{self.name}"')
206
- time_delta = time.time() - self.__last_run_time
207
- if time_delta < self.min_interval:
208
- sleep(self.min_interval - time_delta)
209
- # 依次执行 block
210
- done = False
211
- for block in self.blocks:
212
- block()
213
- if self.finished:
214
- done = True
215
- break
216
- if done:
217
- break
218
-
219
- self.__last_run_time = time.time()
220
- if self.timeout_value and time.time() - self.__last_run_time > self.timeout_value:
221
- if self.timeout_critical:
222
- raise TimeoutError(f'Dispatcher "{self.name}" timed out.')
223
- else:
224
- self.logger.warning(f'Dispatcher "{self.name}" timed out.')
225
- self.result = self.timeout_result
226
- break
227
- device.screenshot()
1
+ import time
2
+ import logging
3
+ from dataclasses import dataclass
4
+ from typing import Any, Callable, Literal
5
+
6
+ from dataclasses import dataclass
7
+
8
+ from kotonebot.backend.ocr import StringMatchFunction
9
+ from kotonebot.primitives import Rect, is_rect
10
+
11
+ from .core import Image
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+ @dataclass
16
+ class ClickParams:
17
+ finish: bool = False
18
+ log: str | None = None
19
+
20
+ class ClickCenter:
21
+ def __init__(self, sd: 'SimpleDispatcher', target: Image | str | StringMatchFunction | Literal['center'], *, params: ClickParams = ClickParams()):
22
+ self.target = target
23
+ self.params = params
24
+ self.sd = sd
25
+
26
+ def __call__(self):
27
+ from kotonebot import device
28
+ if self.params.log:
29
+ self.sd.logger.info(self.params.log)
30
+ device.click_center()
31
+ if self.params.finish:
32
+ self.sd.finished = True
33
+
34
+ class ClickImage:
35
+ def __init__(self, sd: 'SimpleDispatcher', image: Image, *, params: ClickParams = ClickParams()):
36
+ self.image = image
37
+ self.params = params
38
+ self.sd = sd
39
+
40
+ def __call__(self):
41
+ from kotonebot import device, image
42
+ if image.find(self.image):
43
+ if self.params.log:
44
+ self.sd.logger.info(self.params.log)
45
+ device.click()
46
+ if self.params.finish:
47
+ self.sd.finished = True
48
+
49
+ class ClickImageAny:
50
+ def __init__(self, sd: 'SimpleDispatcher', images: list[Image], params: ClickParams = ClickParams()):
51
+ self.images = images
52
+ self.params = params
53
+ self.sd = sd
54
+
55
+ def __call__(self):
56
+ from kotonebot import device, image
57
+ if image.find_multi(self.images):
58
+ if self.params.log:
59
+ self.sd.logger.info(self.params.log)
60
+ device.click()
61
+ if self.params.finish:
62
+ self.sd.finished = True
63
+
64
+ class ClickText:
65
+ def __init__(
66
+ self,
67
+ sd: 'SimpleDispatcher',
68
+ text: str | StringMatchFunction,
69
+ params: ClickParams = ClickParams()
70
+ ):
71
+ self.text = text
72
+ self.params = params
73
+ self.sd = sd
74
+
75
+ def __call__(self):
76
+ from kotonebot import device, ocr
77
+ if ocr.find(self.text):
78
+ if self.params.log:
79
+ self.sd.logger.info(self.params.log)
80
+ device.click()
81
+ if self.params.finish:
82
+ self.sd.finished = True
83
+
84
+ class ClickRect:
85
+ def __init__(self, sd: 'SimpleDispatcher', rect: Rect, *, params: ClickParams = ClickParams()):
86
+ self.rect = rect
87
+ self.params = params
88
+ self.sd = sd
89
+
90
+ def __call__(self):
91
+ from kotonebot import device
92
+ if device.click(self.rect):
93
+ if self.params.log:
94
+ self.sd.logger.info(self.params.log)
95
+ if self.params.finish:
96
+ self.sd.finished = True
97
+
98
+ class UntilText:
99
+ def __init__(
100
+ self,
101
+ sd: 'SimpleDispatcher',
102
+ text: str | StringMatchFunction,
103
+ *,
104
+ rect: Rect | None = None,
105
+ result: Any | None = None
106
+ ):
107
+ self.text = text
108
+ self.sd = sd
109
+ self.rect = rect
110
+ self.result = result
111
+
112
+ def __call__(self):
113
+ from kotonebot import ocr
114
+ if ocr.find(self.text, rect=self.rect):
115
+ self.sd.finished = True
116
+ self.sd.result = self.result
117
+
118
+ class UntilImage:
119
+ def __init__(
120
+ self,
121
+ sd: 'SimpleDispatcher',
122
+ image: Image,
123
+ *,
124
+ rect: Rect | None = None,
125
+ result: Any | None = None
126
+ ):
127
+ self.image = image
128
+ self.sd = sd
129
+ self.rect = rect
130
+ self.result = result
131
+
132
+ def __call__(self):
133
+ from kotonebot import image
134
+ if self.rect:
135
+ logger.warning(f'UntilImage with rect is deprecated. Use UntilText instead.')
136
+ if image.find(self.image):
137
+ self.sd.finished = True
138
+ self.sd.result = self.result
139
+
140
+ class SimpleDispatcher:
141
+ def __init__(self, name: str, *, min_interval: float = 0.3):
142
+ self.name = name
143
+ self.logger = logging.getLogger(f'SimpleDispatcher of {name}')
144
+ self.blocks: list[Callable] = []
145
+ self.finished: bool = False
146
+ self.result: Any | None = None
147
+ self.min_interval = min_interval
148
+ self.timeout_value: float | None = None
149
+ self.timeout_critical: bool = False
150
+ self.__last_run_time: float = 0
151
+
152
+ def click(
153
+ self,
154
+ target: Image | StringMatchFunction | Literal['center'] | Rect,
155
+ *,
156
+ finish: bool = False,
157
+ log: str | None = None
158
+ ):
159
+ params = ClickParams(finish=finish, log=log)
160
+ if isinstance(target, Image):
161
+ self.blocks.append(ClickImage(self, target, params=params))
162
+ elif is_rect(target):
163
+ self.blocks.append(ClickRect(self, target, params=params))
164
+ elif callable(target):
165
+ self.blocks.append(ClickText(self, target, params=params))
166
+ elif target == 'center':
167
+ self.blocks.append(ClickCenter(self, target='center', params=params))
168
+ else:
169
+ raise ValueError(f'Invalid target: {target}')
170
+ return self
171
+
172
+ def click_any(
173
+ self,
174
+ target: list[Image],
175
+ *,
176
+ finish: bool = False,
177
+ log: str | None = None
178
+ ):
179
+ params = ClickParams(finish=finish, log=log)
180
+ self.blocks.append(ClickImageAny(self, target, params))
181
+ return self
182
+
183
+ def until(
184
+ self,
185
+ text: StringMatchFunction | Image,
186
+ *,
187
+ rect: Rect | None = None,
188
+ result: Any | None = None
189
+ ):
190
+ if isinstance(text, Image):
191
+ self.blocks.append(UntilImage(self, text, rect=rect, result=result))
192
+ else:
193
+ self.blocks.append(UntilText(self, text, rect=rect, result=result))
194
+ return self
195
+
196
+ def timeout(self, timeout: float, *, critical: bool = False, result: Any | None = None):
197
+ self.timeout_value = timeout
198
+ self.timeout_critical = critical
199
+ self.timeout_result = result
200
+ return self
201
+
202
+ def run(self):
203
+ from kotonebot import device, sleep
204
+ while True:
205
+ logger.debug(f'Running dispatcher "{self.name}"')
206
+ time_delta = time.time() - self.__last_run_time
207
+ if time_delta < self.min_interval:
208
+ sleep(self.min_interval - time_delta)
209
+ # 依次执行 block
210
+ done = False
211
+ for block in self.blocks:
212
+ block()
213
+ if self.finished:
214
+ done = True
215
+ break
216
+ if done:
217
+ break
218
+
219
+ self.__last_run_time = time.time()
220
+ if self.timeout_value and time.time() - self.__last_run_time > self.timeout_value:
221
+ if self.timeout_critical:
222
+ raise TimeoutError(f'Dispatcher "{self.name}" timed out.')
223
+ else:
224
+ self.logger.warning(f'Dispatcher "{self.name}" timed out.')
225
+ self.result = self.timeout_result
226
+ break
227
+ device.screenshot()
228
228
  return self.result