diff --git a/src/atm/config.py b/src/atm/config.py index 4ff6ba2..35aafa2 100644 --- a/src/atm/config.py +++ b/src/atm/config.py @@ -78,6 +78,9 @@ class DiscordCfg: class TelegramCfg: bot_token: str chat_id: str + allowed_chat_ids: tuple[str, ...] = () + poll_timeout_s: int = 30 + auto_poll_interval_s: int = 180 def __post_init__(self) -> None: if not self.bot_token or not self.chat_id: @@ -156,9 +159,14 @@ class Config: drift_threshold=int(data["canary"].get("drift_threshold", 8)), ) discord = DiscordCfg(webhook_url=data["discord"]["webhook_url"]) + tg = data["telegram"] + _allowed = [str(c) for c in tg.get("allowed_chat_ids", [])] or [str(tg["chat_id"])] telegram = TelegramCfg( - bot_token=data["telegram"]["bot_token"], - chat_id=str(data["telegram"]["chat_id"]), + bot_token=tg["bot_token"], + chat_id=str(tg["chat_id"]), + allowed_chat_ids=tuple(_allowed), + poll_timeout_s=int(tg.get("poll_timeout_s", 30)), + auto_poll_interval_s=int(tg.get("auto_poll_interval_s", 180)), ) opts = data.get("options", {}) region = None diff --git a/src/atm/detector.py b/src/atm/detector.py index f2c3d82..e2bc603 100644 --- a/src/atm/detector.py +++ b/src/atm/detector.py @@ -28,6 +28,7 @@ class DetectionResult: match: ColorMatch | None # None if no dot accepted: bool # post-debounce; True only when match repeats debounce_depth times color: str | None # accepted color name (UNKNOWN excluded) + dot_pos_abs: tuple[int, int] | None = None # absolute (x, y) in frame; set when dot_found class Detector: @@ -60,8 +61,14 @@ class Detector: self._debounce: deque[str | None] = deque(maxlen=cfg.debounce_depth) self._rolling: deque[DetectionResult] = deque(maxlen=20) - def step(self, ts: float) -> DetectionResult: - frame = self._capture() + def step(self, ts: float, frame=None) -> DetectionResult: + """Run one detection tick. + + frame: pre-captured BGR ndarray (from asyncio.to_thread capture). When + None (default), calls self._capture() — preserving the sync-loop behaviour. + """ + if frame is None: + frame = self._capture() if frame is None: self._debounce.append(None) @@ -117,6 +124,7 @@ class Detector: match=match, accepted=accepted, color=color, + dot_pos_abs=(self._cfg.dot_roi.x + x, self._cfg.dot_roi.y + y), ) self._rolling.append(r) return r