60 lines
1.5 KiB
Python
60 lines
1.5 KiB
Python
from __future__ import annotations
|
|
|
|
from core.device_manager import DeviceManager
|
|
from core.models import Scene, SceneElement
|
|
from tools.describe_screen import describe_screen
|
|
|
|
|
|
def find_text(
|
|
scene: Scene,
|
|
query: str,
|
|
*,
|
|
exact: bool = False,
|
|
case_sensitive: bool = False,
|
|
) -> dict[str, object]:
|
|
match = _find_element(scene, query, exact=exact, case_sensitive=case_sensitive)
|
|
if not match:
|
|
return {"found": False, "query": query, "reason": "not found"}
|
|
x, y = match.center
|
|
return {
|
|
"found": True,
|
|
"query": query,
|
|
"x": x,
|
|
"y": y,
|
|
"element": match.to_dict(),
|
|
}
|
|
|
|
|
|
def find_text_on_screen(
|
|
query: str,
|
|
*,
|
|
device_id: str | None = None,
|
|
manager: DeviceManager | None = None,
|
|
exact: bool = False,
|
|
case_sensitive: bool = False,
|
|
) -> dict[str, object]:
|
|
return find_text(
|
|
describe_screen(device_id, manager=manager),
|
|
query,
|
|
exact=exact,
|
|
case_sensitive=case_sensitive,
|
|
)
|
|
|
|
|
|
def _find_element(
|
|
scene: Scene,
|
|
query: str,
|
|
*,
|
|
exact: bool,
|
|
case_sensitive: bool,
|
|
) -> SceneElement | None:
|
|
needle = query if case_sensitive else query.casefold()
|
|
for element in scene.elements:
|
|
if not element.text:
|
|
continue
|
|
haystack = element.text if case_sensitive else element.text.casefold()
|
|
matched = haystack == needle if exact else needle in haystack
|
|
if matched:
|
|
return element
|
|
return None
|