tvsignals-to-tg/app/telegram.py
Artemii Peretiachenko 15efda5e0d Allow forum topic id in webhook URL path.
TradingView alerts can target different topics via /h/{secret}/{thread_id}
while keeping the same payload; bare /h/{secret} still uses the env default.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-24 20:22:55 +02:00

61 lines
1.7 KiB
Python

from __future__ import annotations
import logging
import httpx
from app.config import Settings
logger = logging.getLogger(__name__)
TELEGRAM_API = "https://api.telegram.org"
class TelegramError(Exception):
pass
async def send_photo(
settings: Settings,
*,
photo: bytes,
caption: str,
message_thread_id: int,
filename: str = "setup.png",
) -> dict:
url = f"{TELEGRAM_API}/bot{settings.telegram_bot_token}/sendPhoto"
data = {
"chat_id": settings.telegram_chat_id,
"message_thread_id": str(message_thread_id),
"caption": caption,
"parse_mode": "HTML",
}
files = {"photo": (filename, photo, "image/png")}
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.post(url, data=data, files=files)
payload = response.json()
if response.status_code >= 400 or not payload.get("ok"):
raise TelegramError(f"sendPhoto failed: {payload}")
return payload
async def send_message(
settings: Settings,
*,
text: str,
message_thread_id: int,
) -> dict:
url = f"{TELEGRAM_API}/bot{settings.telegram_bot_token}/sendMessage"
data = {
"chat_id": settings.telegram_chat_id,
"message_thread_id": str(message_thread_id),
"text": text,
"parse_mode": "HTML",
"disable_web_page_preview": True,
}
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.post(url, data=data)
payload = response.json()
if response.status_code >= 400 or not payload.get("ok"):
raise TelegramError(f"sendMessage failed: {payload}")
return payload