"""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