feat: capture message_thread_id for Telegram topic routing

This commit is contained in:
daniel
2026-05-12 14:05:00 -05:00
parent 3a49dadb69
commit 9d3a93a998
24 changed files with 1442 additions and 73 deletions

View File

@@ -7,8 +7,9 @@ import boto3
class TelegramAdapter:
"""Channel adapter for Telegram Bot API."""
def __init__(self, chat_id: str, bot_token_secret_arn: str = ''):
def __init__(self, chat_id: str, bot_token_secret_arn: str = '', message_thread_id: int | None = None):
self.chat_id = str(chat_id)
self.thread_id = message_thread_id # None for regular chats, int for supergroup topics
self._secret_arn = bot_token_secret_arn
self._token: str | None = None
self._lock = threading.Lock()
@@ -36,31 +37,37 @@ class TelegramAdapter:
def send(self, text: str) -> str:
"""Send message, return message_id."""
resp = self._api('sendMessage', {
payload: dict = {
'chat_id': self.chat_id,
'text': text,
'parse_mode': 'Markdown',
})
}
if self.thread_id is not None:
payload['message_thread_id'] = self.thread_id
resp = self._api('sendMessage', payload)
return str(resp.get('result', {}).get('message_id', ''))
def send_typing(self) -> None:
"""Send typing action (best-effort)."""
try:
self._api('sendChatAction', {
'chat_id': self.chat_id,
'action': 'typing',
})
payload: dict = {'chat_id': self.chat_id, 'action': 'typing'}
if self.thread_id is not None:
payload['message_thread_id'] = self.thread_id
self._api('sendChatAction', payload)
except Exception:
pass
def edit(self, message_id: str, text: str) -> None:
"""Edit an existing message in-place."""
try:
self._api('editMessageText', {
payload: dict = {
'chat_id': self.chat_id,
'message_id': int(message_id),
'text': text,
'parse_mode': 'Markdown',
})
}
if self.thread_id is not None:
payload['message_thread_id'] = self.thread_id
self._api('editMessageText', payload)
except Exception:
pass

View File

@@ -64,6 +64,7 @@ def main(payload: dict, context) -> dict:
adapter = TelegramAdapter(
chat_id=adapter_config.get('target_id', ''),
bot_token_secret_arn=adapter_config.get('bot_token_secret_arn', ''),
message_thread_id=adapter_config.get('message_thread_id'),
)
else:
# Future channels: instantiate appropriate adapter