"""Telegram Bot with webhook mode for HF Spaces.""" import asyncio from telegram import Update, Bot from telegram.ext import Application, CommandHandler, ContextTypes from fastapi import Request from app.config import get_settings class TelegramBot: """Telegram bot with webhook handlers.""" _app: Application = None _bot: Bot = None _started = False _webhook_url: str = None @classmethod async def setup(cls, webhook_base_url: str = None): """ Setup the Telegram bot (webhook mode). Call this during app startup. """ settings = get_settings() if not settings.telegram_bot_token: print("Telegram bot: Not configured (no token)") return False try: cls._bot = Bot(token=settings.telegram_bot_token) cls._app = Application.builder().token(settings.telegram_bot_token).build() # Add handlers cls._app.add_handler(CommandHandler("start", cls._handle_start)) cls._app.add_handler(CommandHandler("help", cls._handle_help)) cls._app.add_handler(CommandHandler("chatid", cls._handle_chatid)) cls._app.add_handler(CommandHandler("top", cls._handle_top)) cls._app.add_handler(CommandHandler("watchlist", cls._handle_watchlist)) # Initialize app (but don't start polling) await cls._app.initialize() # Set webhook if URL provided if webhook_base_url: cls._webhook_url = f"{webhook_base_url}/api/v1/telegram/webhook" await cls._bot.set_webhook(url=cls._webhook_url) print(f"Telegram bot: Webhook set to {cls._webhook_url}") cls._started = True print("Telegram bot: Initialized successfully") return True except Exception as e: print(f"Telegram bot: Failed to setup ({e.__class__.__name__}: {e})") cls._app = None cls._bot = None cls._started = False return False @classmethod async def process_update(cls, update_data: dict): """Process incoming webhook update.""" if not cls._app or not cls._started: return False try: update = Update.de_json(update_data, cls._bot) await cls._app.process_update(update) return True except Exception as e: print(f"Telegram bot: Error processing update ({e})") return False @classmethod async def shutdown(cls): """Shutdown the bot.""" if cls._app and cls._started: try: # Remove webhook if cls._bot: await cls._bot.delete_webhook() await cls._app.shutdown() print("Telegram bot: Shutdown complete") except Exception as e: print(f"Telegram bot: Error during shutdown ({e})") @classmethod async def _handle_start(cls, update: Update, context: ContextTypes.DEFAULT_TYPE): """Handle /start command.""" chat_id = update.effective_chat.id message = ( f"🚀 MEXC FR Report Bot\n\n" f"📍 Your Chat ID: {chat_id}\n\n" f"Copy this Chat ID and add it to your .env file:\n" f"TELEGRAM_CHAT_ID={chat_id}\n\n" f"Commands:\n" f"/top - Get Top 5 FR coins\n" f"/watchlist - Get watchlist coins\n" f"/chatid - Get your chat ID\n" f"/help - Show help" ) await update.message.reply_text(message, parse_mode="HTML") @classmethod async def _handle_help(cls, update: Update, context: ContextTypes.DEFAULT_TYPE): """Handle /help command.""" message = ( "📖 MEXC FR Report Bot Help\n\n" "Commands:\n" "/start - Start bot and get chat ID\n" "/top - Get Top 5 positive/negative FR\n" "/watchlist - Get watched coins FR\n" "/chatid - Get your chat ID\n\n" "Auto notifications:\n" "Every hour the bot will send:\n" "• Top 5 highest FR (short opportunity)\n" "• Top 5 lowest FR (long opportunity)\n" "• Your watchlist coins update" ) await update.message.reply_text(message, parse_mode="HTML") @classmethod async def _handle_chatid(cls, update: Update, context: ContextTypes.DEFAULT_TYPE): """Handle /chatid command.""" chat_id = update.effective_chat.id await update.message.reply_text( f"📍 Your Chat ID: {chat_id}", parse_mode="HTML" ) @classmethod async def _handle_top(cls, update: Update, context: ContextTypes.DEFAULT_TYPE): """Handle /top command - send top FR coins.""" from app.services.telegram_service import get_telegram_service service = get_telegram_service() chat_id = update.effective_chat.id await service.send_top_fr_notification(chat_id=chat_id) @classmethod async def _handle_watchlist(cls, update: Update, context: ContextTypes.DEFAULT_TYPE): """Handle /watchlist command - send watchlist coins.""" from app.services.telegram_service import get_telegram_service service = get_telegram_service() chat_id = update.effective_chat.id success = await service.send_watchlist_notification(chat_id=chat_id) if not success: await update.message.reply_text( "📭 Watchlist is empty. Add coins via API:\n" "POST /api/v1/watchlist", parse_mode="HTML" ) def get_telegram_bot(): return TelegramBot