T0X1N's picture
chore: codebase audit and fixes (ruff, mypy, pytest)
9659593
"""
MediGuard AI — Telegram Bot
Lightweight Telegram bot that proxies user messages to the /ask endpoint.
Requires ``python-telegram-bot`` (installed via extras ``[telegram]``).
"""
from __future__ import annotations
import logging
import os
logger = logging.getLogger(__name__)
# Lazy import — only needed when the bot is actually started
_Application = None
def _get_telegram():
global _Application
try:
from telegram import Update
from telegram.ext import Application, CommandHandler, MessageHandler, filters
_Application = Application
return Update, Application, CommandHandler, MessageHandler, filters
except ImportError:
raise ImportError(
"python-telegram-bot is required for the Telegram bot. "
"Install it with: pip install 'mediguard[telegram]' or pip install python-telegram-bot"
)
class MediGuardTelegramBot:
"""Telegram bot that wraps a ``requests`` call to the API ``/ask`` endpoint."""
def __init__(
self,
token: str | None = None,
api_base_url: str = "http://localhost:8000",
) -> None:
self._token = token or os.getenv("TELEGRAM_BOT_TOKEN", "")
self._api_base = api_base_url.rstrip("/")
if not self._token:
raise ValueError("TELEGRAM_BOT_TOKEN is required")
def run(self) -> None:
"""Start the bot (blocking)."""
import httpx
Update, Application, CommandHandler, MessageHandler, filters = _get_telegram()
app = Application.builder().token(self._token).build()
async def start_handler(update: Update, context) -> None:
await update.message.reply_text(
"Welcome to MediGuard AI! Send me a medical question or biomarker values "
"and I'll provide evidence-based insights.\n\n"
"Disclaimer: This is not a substitute for professional medical advice."
)
async def help_handler(update: Update, context) -> None:
await update.message.reply_text(
"Send me:\n"
"• A medical question (e.g. 'What does high HbA1c mean?')\n"
"• Biomarker values (e.g. 'My glucose is 180 and HbA1c 8.2')\n\n"
"I'll provide evidence-based analysis."
)
async def message_handler(update: Update, context) -> None:
user_text = update.message.text or ""
if not user_text.strip():
return
await update.message.reply_text("Analyzing… please wait.")
try:
async with httpx.AsyncClient(timeout=60.0) as client:
resp = await client.post(
f"{self._api_base}/ask",
json={"question": user_text},
)
resp.raise_for_status()
data = resp.json()
answer = data.get("answer", "Sorry, I could not generate an answer.")
except Exception as exc:
logger.error("Telegram→API call failed: %s", exc)
answer = "Sorry, I'm having trouble processing your request right now."
# Telegram max message = 4096 chars
if len(answer) > 4000:
answer = answer[:4000] + "\n\n… (truncated)"
await update.message.reply_text(answer)
app.add_handler(CommandHandler("start", start_handler))
app.add_handler(CommandHandler("help", help_handler))
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, message_handler))
logger.info("Telegram bot starting (polling mode)")
app.run_polling()