[Python] TelegramBot inside FastAPI is not responding to chat commands, like "/start"

Discussão em 'Python' iniciado por Stack, Maio 21, 2025.

  1. Stack

    Stack Membro Participativo

    My code is designed to fetch various announcements and redirect it into different channels of Telegram, after some preprocessing. My problem is that telegram bot works just fine. It sends messages as expected. But lately i wished to add some more functionality for which i need users to be able to send commands to my bot.

    I went to the docs and set the scope correctly, gave permissions, registered other handlers but telegram-bot simply doesnt respond to commands. i will handle reaction for various commands lately, but for now i am really struggled and do not understand why bot doesn't react. In other projects without FastAPI it works as usual. Here is my telegram.py:

    class Notifier:
    def __init__(self):
    self.logger = logging.getLogger(__name__)
    self.db_pool = None
    self.polling_task = None
    self.chat_ids = {
    "Trading channel": settings.TELEGRAM_TRADING_CHAT_ID,
    "Engineering channel": settings.TELEGRAM_ENGINEERING_CHAT_ID
    }
    self.forex_factory = ForexFactoryService()

    self.application = ApplicationBuilder() \
    .token(settings.TELEGRAM_BOT_TOKEN) \
    .build()

    self._register_handlers()

    async def connect_db(self):
    if not self.db_pool:
    self.db_pool = await asyncpg.create_pool(
    dsn=settings.DATABASE_URL,
    min_size=1,
    max_size=5,
    command_timeout=60
    )

    def _register_handlers(self):
    self.application.add_handler(CommandHandler("start", self._handle_start))
    self.application.add_handler(CommandHandler("news", self._handle_news))
    self.application.add_handler(CommandHandler("forex", self._handle_forex))
    self.application.add_handler(CallbackQueryHandler(self._handle_button_press))
    print("✅ Telegramm Handlers registered")

    async def send(self, message: str, channel: str = "Trading channel") -> bool:
    try:
    chat_id = self.chat_ids.get(channel)
    if not chat_id:
    self.logger.error(f"Chat ID for '{channel}' not found.")
    return False

    await self.application.bot.send_message(
    chat_id=chat_id,
    text=message,
    disable_web_page_preview=True
    )
    return True

    except Exception as e:
    self.logger.error(f"Failed to send message: {e}")
    self.logger.debug(f"Message: {message[:200]}")
    return False

    async def get_latest_news(self, limit: int = 10) -> List[Dict]:
    if not self.db_pool:
    await self.connect_db()

    async with self.db_pool.acquire() as conn:
    return await conn.fetch(
    """
    SELECT id, title, content, url, publish_time, exchange
    FROM announcements
    ORDER BY publish_time DESC
    LIMIT $1
    """,
    limit
    )

    async def forex_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
    await update.message.reply_text("Fetching today's Forex events...")
    message = await self.forex_factory.get_formatted_events()
    await update.message.reply_text(message, parse_mode="Markdown")

    async def _handle_start(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
    commands = [
    BotCommand("news", "Get latest announcements"),
    BotCommand("forex", "Forex Factory economic data"),
    BotCommand("help", "Show help information")
    ]
    await context.bot.set_my_commands(commands, scope=BotCommandScopeDefault())
    print("Registered commands:", [c.command for c in commands])
    await update.message.reply_text(
    " Financial News Bot\n\n"
    "Available commands:\n"
    "/news - Latest announcements\n"
    "/forex - Economic calendar data"
    )

    async def _handle_news(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
    try:
    news_items = await self.get_latest_news()
    if not news_items:
    await update.message.reply_text("No recent announcements found.")
    return

    response = [" Latest Announcements:\n"]
    for item in news_items:
    response.append(
    f"• [{item['exchange'].upper()}] {item['title']}\n"
    f" {item['publish_time'].strftime('%Y-%m-%d %H:%M')}\n"
    f" {item['url']}\n"
    )
    await update.message.reply_text("\n".join(response))
    except Exception as e:
    self.logger.error(f"Failed to handle /news: {e}")
    await update.message.reply_text("❌ Error fetching news")

    async def _handle_forex(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
    try:
    success = await self.forex_factory.send_to_telegram()
    if not success:
    await update.message.reply_text("Failed to fetch Forex Factory data.")
    except Exception as e:
    self.logger.error(f"Error in /forex command: {e}")
    await update.message.reply_text("❌ Error processing Forex data")

    async def _handle_button_press(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()

    if query.data == "refresh_news":
    await self._handle_news(update, context)
    elif query.data == "refresh_forex":
    await self._handle_forex(update, context)
    else:
    await query.edit_message_text("Unknown command.")

    async def start(self):
    print(" Telegram bot is starting...")
    await self.connect_db()
    await self.application.initialize()
    await self.application.start()

    # Start polling as a background task
    self.polling_task = asyncio.create_task(self.application.updater.start_polling())
    await self.polling_task
    print("✅ Bot is now polling for updates")

    async def stop(self):
    if self.polling_task:
    self.polling_task.cancel()
    try:
    await self.polling_task
    except asyncio.CancelledError:
    print(" Polling task cancelled")

    await self.application.stop()
    await self.application.shutdown()
    if self.db_pool:
    await self.db_pool.close()
    print(" Bot stopped")


    And also here is my main.py for fastAPI:

    @asynccontextmanager
    async def lifespan(app: FastAPI):
    logger.info(" Starting application...")

    storage = AnnouncementStorage()
    await storage.connect()
    print("Connected to DataBase successfully")
    telegram_bot = Notifier()
    analyzer = AnnouncementAnalyzer(storage)
    analyzer.notifier = telegram_bot

    app.state.telegram_bot = telegram_bot
    app.state.analyzer = analyzer

    # Start services
    try:
    await telegram_bot.start()
    app.state.analyzer_task = asyncio.create_task(analyzer.run(interval_seconds=300))
    logger.info("✅ Services started")
    yield
    except Exception as e:
    logger.error(f"❌ Startup failed: {e}")
    raise
    finally:
    logger.info(" Shutting down...")
    if hasattr(app.state, 'analyzer_task'):
    app.state.analyzer_task.cancel()
    try:
    await app.state.analyzer_task
    except asyncio.CancelledError:
    logger.info("Analyzer task cancelled")

    if hasattr(app.state, 'telegram_bot'):
    await app.state.telegram_bot.stop()
    logger.info("Telegram bot stopped")

    if storage and hasattr(storage, 'pool'):
    await storage.pool.close()
    logger.info("️ Database connection closed")

    app = FastAPI(lifespan=lifespan)

    # other code for healthcheck and accessing latest news from api

    app.include_router(router, prefix="/api")


    It doesnt crash, it just doesnt respond. it simply continues sending messages to the needed channels.

    Continue reading...

Compartilhe esta Página