Spaces:
Running
Running
| """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 | |
| 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 | |
| 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 | |
| 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})") | |
| async def _handle_start(cls, update: Update, context: ContextTypes.DEFAULT_TYPE): | |
| """Handle /start command.""" | |
| chat_id = update.effective_chat.id | |
| message = ( | |
| f"π <b>MEXC FR Report Bot</b>\n\n" | |
| f"π Your Chat ID: <code>{chat_id}</code>\n\n" | |
| f"Copy this Chat ID and add it to your .env file:\n" | |
| f"<code>TELEGRAM_CHAT_ID={chat_id}</code>\n\n" | |
| f"<b>Commands:</b>\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") | |
| async def _handle_help(cls, update: Update, context: ContextTypes.DEFAULT_TYPE): | |
| """Handle /help command.""" | |
| message = ( | |
| "π <b>MEXC FR Report Bot Help</b>\n\n" | |
| "<b>Commands:</b>\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" | |
| "<b>Auto notifications:</b>\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") | |
| 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: <code>{chat_id}</code>", | |
| parse_mode="HTML" | |
| ) | |
| 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) | |
| 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" | |
| "<code>POST /api/v1/watchlist</code>", | |
| parse_mode="HTML" | |
| ) | |
| def get_telegram_bot(): | |
| return TelegramBot | |