diff --git a/bridge.py b/bridge.py
index 9c6707a..6b40ef9 100644
--- a/bridge.py
+++ b/bridge.py
@@ -44,22 +44,29 @@ async def on_tracker_event(event: dict):
return
if event_type == "message.new":
- msg = event.get("data", {})
- author = msg.get("author", {})
- logger.info("message.new from %s: %s", author.get("slug", "?"), (msg.get("content", ""))[:50])
+ data = event.get("data", {})
+ actor = data.get("actor") or {}
+ payload = data.get("payload") or {}
+ evt_type = data.get("type", "")
+ content = payload.get("content", "")
+
+ logger.info("message.new type=%s from %s: %s", evt_type, actor.get("slug", "?"), content[:50])
+
+ # Only forward chat messages (not task_comment, task_status, etc.)
+ if evt_type not in ("chat_message",):
+ return
# Skip messages from bridge itself (avoid echo)
- author_slug = author.get("slug", "")
- if author_slug == "bridge":
+ actor_slug = actor.get("slug", "")
+ if actor_slug == "bridge":
return
# Skip messages that bridge sent on behalf of Telegram users
# (they contain "[Username]" prefix)
- text_content = msg.get("content", "")
- if text_content.startswith("[") and "] " in text_content[:50]:
+ if content.startswith("[") and "] " in content[:50]:
return
- project_id = msg.get("project_id")
+ project_id = data.get("project_id")
if not project_id:
return
@@ -67,13 +74,11 @@ async def on_tracker_event(event: dict):
if not topic_id:
return
- author_name = author.get("name", author.get("slug", "???"))
- text = msg.get("content", "")
- if not text:
+ if not content:
return
- # Format: "Author: message"
- tg_text = f"{_escape_html(author_name)}: {_escape_html(text)}"
+ actor_name = actor.get("name", actor.get("slug", "???"))
+ tg_text = f"{_escape_html(actor_name)}: {_escape_html(content)}"
# Silent if any human is online in web
silent = any(s for s in _online_members if s not in ("coder", "architect", "bridge"))
await _send_to_topic(topic_id, tg_text, silent=silent)
diff --git a/tracker_client.py b/tracker_client.py
index 27dd099..a875b19 100644
--- a/tracker_client.py
+++ b/tracker_client.py
@@ -5,7 +5,6 @@ import json
import logging
from typing import Callable, Awaitable
-import httpx
import websockets
from config import Config
@@ -21,7 +20,6 @@ class TrackerClient:
self.on_message = on_message
self._ws = None
self._running = False
- self._project_chat_ids: dict[str, str] = {} # project_uuid -> chat_id
self._send_queue: asyncio.Queue = asyncio.Queue()
async def connect(self):
@@ -35,7 +33,6 @@ class TrackerClient:
self._ws = ws
logger.info("Connected to Tracker WS")
- # Run reader, writer and heartbeat concurrently
await asyncio.gather(
self._reader(ws),
self._writer(ws),
@@ -84,7 +81,6 @@ class TrackerClient:
if event_type == "auth.ok":
logger.info("Authenticated as bridge")
- await self._cache_projects()
return
if event_type == "error":
@@ -100,63 +96,19 @@ class TrackerClient:
if event_type in ("message.new", "task.updated", "task.created", "project.created"):
await self.on_message(event)
- async def _cache_projects(self):
- """Fetch all projects and cache their chat_ids."""
- try:
- async with httpx.AsyncClient() as client:
- resp = await client.get(
- f"{self.config.tracker_url}/api/v1/projects",
- headers={"Authorization": f"Bearer {self.config.bridge_token}"},
- )
- if resp.status_code == 200:
- for p in resp.json():
- pid = p.get("id")
- cid = p.get("chat_id")
- if pid and cid:
- self._project_chat_ids[pid] = cid
- logger.info("Cached %d project chat_ids", len(self._project_chat_ids))
- except Exception as e:
- logger.error("Failed to cache projects: %s", e)
-
- async def get_chat_id(self, project_uuid: str) -> str | None:
- """Get chat_id for a project, fetching if not cached."""
- if project_uuid in self._project_chat_ids:
- return self._project_chat_ids[project_uuid]
-
- # Try to fetch
- try:
- async with httpx.AsyncClient() as client:
- resp = await client.get(
- f"{self.config.tracker_url}/api/v1/projects/{project_uuid}",
- headers={"Authorization": f"Bearer {self.config.bridge_token}"},
- )
- if resp.status_code == 200:
- cid = resp.json().get("chat_id")
- if cid:
- self._project_chat_ids[project_uuid] = cid
- return cid
- except Exception as e:
- logger.error("Failed to fetch project %s: %s", project_uuid[:8], e)
- return None
-
- async def send_message(self, project_uuid: str, text: str):
- """Send a chat message to Tracker."""
+ async def send_message(self, project_id: str, text: str):
+ """Send a chat message to Tracker via WS chat.send."""
if not self._ws:
logger.warning("Not connected to Tracker")
return
- chat_id = await self.get_chat_id(project_uuid)
- if not chat_id:
- logger.warning("No chat_id for project %s", project_uuid[:8])
- return
-
payload = {
"type": "chat.send",
- "chat_id": chat_id,
+ "project_id": project_id,
"content": text,
}
await self._send_queue.put(payload)
- logger.info("Queued to Tracker: project=%s chat=%s", project_uuid[:8], chat_id[:8])
+ logger.info("Queued to Tracker: project=%s", project_id[:8])
def stop(self):
self._running = False