|
@@ -5,10 +5,10 @@ Core Telegram Bot - Handles only bot setup, authentication, and basic messaging.
|
|
|
|
|
|
import asyncio
|
|
|
import logging
|
|
|
-# import telegram # Import telegram to check version (NO LONGER NEEDED)
|
|
|
+import telegram # Import telegram to check version
|
|
|
from datetime import datetime
|
|
|
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
|
|
|
-from telegram.ext import Application, ContextTypes, CommandHandler, CallbackQueryHandler, MessageHandler, filters
|
|
|
+from telegram.ext import Application, ContextTypes, CommandHandler, CallbackQueryHandler, MessageHandler, filters, Updater
|
|
|
|
|
|
from src.config.config import Config
|
|
|
from src.trading.trading_engine import TradingEngine
|
|
@@ -65,45 +65,47 @@ class TelegramTradingBot:
|
|
|
if not self.application:
|
|
|
return
|
|
|
|
|
|
+ dp = self.application.dispatcher # Get dispatcher for v13.x
|
|
|
+
|
|
|
# Basic bot commands
|
|
|
- self.application.add_handler(CommandHandler("start", self.start_command))
|
|
|
- self.application.add_handler(CommandHandler("help", self.help_command))
|
|
|
+ dp.add_handler(CommandHandler("start", self.start_command))
|
|
|
+ dp.add_handler(CommandHandler("help", self.help_command))
|
|
|
|
|
|
# Trading commands
|
|
|
- self.application.add_handler(CommandHandler("long", self.trading_commands.long_command))
|
|
|
- self.application.add_handler(CommandHandler("short", self.trading_commands.short_command))
|
|
|
- self.application.add_handler(CommandHandler("exit", self.trading_commands.exit_command))
|
|
|
- self.application.add_handler(CommandHandler("sl", self.trading_commands.sl_command))
|
|
|
- self.application.add_handler(CommandHandler("tp", self.trading_commands.tp_command))
|
|
|
- self.application.add_handler(CommandHandler("coo", self.trading_commands.coo_command))
|
|
|
+ dp.add_handler(CommandHandler("long", self.trading_commands.long_command))
|
|
|
+ dp.add_handler(CommandHandler("short", self.trading_commands.short_command))
|
|
|
+ dp.add_handler(CommandHandler("exit", self.trading_commands.exit_command))
|
|
|
+ dp.add_handler(CommandHandler("sl", self.trading_commands.sl_command))
|
|
|
+ dp.add_handler(CommandHandler("tp", self.trading_commands.tp_command))
|
|
|
+ dp.add_handler(CommandHandler("coo", self.trading_commands.coo_command))
|
|
|
|
|
|
# Info commands
|
|
|
- self.application.add_handler(CommandHandler("balance", self.info_commands.balance_command))
|
|
|
- self.application.add_handler(CommandHandler("positions", self.info_commands.positions_command))
|
|
|
- self.application.add_handler(CommandHandler("orders", self.info_commands.orders_command))
|
|
|
- self.application.add_handler(CommandHandler("stats", self.info_commands.stats_command))
|
|
|
- self.application.add_handler(CommandHandler("trades", self.info_commands.trades_command))
|
|
|
- self.application.add_handler(CommandHandler("market", self.info_commands.market_command))
|
|
|
- self.application.add_handler(CommandHandler("price", self.info_commands.price_command))
|
|
|
- self.application.add_handler(CommandHandler("performance", self.info_commands.performance_command))
|
|
|
- self.application.add_handler(CommandHandler("daily", self.info_commands.daily_command))
|
|
|
- self.application.add_handler(CommandHandler("weekly", self.info_commands.weekly_command))
|
|
|
- self.application.add_handler(CommandHandler("monthly", self.info_commands.monthly_command))
|
|
|
- self.application.add_handler(CommandHandler("risk", self.info_commands.risk_command))
|
|
|
- self.application.add_handler(CommandHandler("balance_adjustments", self.info_commands.balance_adjustments_command))
|
|
|
- self.application.add_handler(CommandHandler("commands", self.info_commands.commands_command))
|
|
|
- self.application.add_handler(CommandHandler("c", self.info_commands.commands_command)) # Alias
|
|
|
+ dp.add_handler(CommandHandler("balance", self.info_commands.balance_command))
|
|
|
+ dp.add_handler(CommandHandler("positions", self.info_commands.positions_command))
|
|
|
+ dp.add_handler(CommandHandler("orders", self.info_commands.orders_command))
|
|
|
+ dp.add_handler(CommandHandler("stats", self.info_commands.stats_command))
|
|
|
+ dp.add_handler(CommandHandler("trades", self.info_commands.trades_command))
|
|
|
+ dp.add_handler(CommandHandler("market", self.info_commands.market_command))
|
|
|
+ dp.add_handler(CommandHandler("price", self.info_commands.price_command))
|
|
|
+ dp.add_handler(CommandHandler("performance", self.info_commands.performance_command))
|
|
|
+ dp.add_handler(CommandHandler("daily", self.info_commands.daily_command))
|
|
|
+ dp.add_handler(CommandHandler("weekly", self.info_commands.weekly_command))
|
|
|
+ dp.add_handler(CommandHandler("monthly", self.info_commands.monthly_command))
|
|
|
+ dp.add_handler(CommandHandler("risk", self.info_commands.risk_command))
|
|
|
+ dp.add_handler(CommandHandler("balance_adjustments", self.info_commands.balance_adjustments_command))
|
|
|
+ dp.add_handler(CommandHandler("commands", self.info_commands.commands_command))
|
|
|
+ dp.add_handler(CommandHandler("c", self.info_commands.commands_command)) # Alias
|
|
|
|
|
|
# Management commands
|
|
|
- self.application.add_handler(CommandHandler("monitoring", self.management_commands.monitoring_command))
|
|
|
- self.application.add_handler(CommandHandler("alarm", self.management_commands.alarm_command))
|
|
|
- self.application.add_handler(CommandHandler("logs", self.management_commands.logs_command))
|
|
|
- self.application.add_handler(CommandHandler("debug", self.management_commands.debug_command))
|
|
|
- self.application.add_handler(CommandHandler("version", self.management_commands.version_command))
|
|
|
- self.application.add_handler(CommandHandler("keyboard", self.management_commands.keyboard_command))
|
|
|
+ dp.add_handler(CommandHandler("monitoring", self.management_commands.monitoring_command))
|
|
|
+ dp.add_handler(CommandHandler("alarm", self.management_commands.alarm_command))
|
|
|
+ dp.add_handler(CommandHandler("logs", self.management_commands.logs_command))
|
|
|
+ dp.add_handler(CommandHandler("debug", self.management_commands.debug_command))
|
|
|
+ dp.add_handler(CommandHandler("version", self.management_commands.version_command))
|
|
|
+ dp.add_handler(CommandHandler("keyboard", self.management_commands.keyboard_command))
|
|
|
|
|
|
# Callback and message handlers
|
|
|
- self.application.add_handler(CallbackQueryHandler(self.trading_commands.button_callback))
|
|
|
+ dp.add_handler(CallbackQueryHandler(self.trading_commands.button_callback))
|
|
|
|
|
|
async def start_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
|
|
"""Handle the /start command."""
|
|
@@ -276,7 +278,7 @@ For support or issues, check the logs or contact the administrator.
|
|
|
logger.error(f"Error sending help message in /help: {e}")
|
|
|
|
|
|
async def run(self):
|
|
|
- """Run the Telegram bot with manual initialization and shutdown."""
|
|
|
+ """Run the Telegram bot (v13.x compatible)."""
|
|
|
if not Config.TELEGRAM_BOT_TOKEN:
|
|
|
logger.error("❌ TELEGRAM_BOT_TOKEN not configured")
|
|
|
return
|
|
@@ -285,77 +287,67 @@ For support or issues, check the logs or contact the administrator.
|
|
|
logger.error("❌ TELEGRAM_CHAT_ID not configured")
|
|
|
return
|
|
|
|
|
|
- # logger.info(f"🔧 Using python-telegram-bot version: {telegram.__version__}") # NO LONGER NEEDED
|
|
|
+ logger.info(f"🔧 Using python-telegram-bot version: {telegram.__version__} (Running in v13.x compatibility mode)")
|
|
|
|
|
|
- # Create application
|
|
|
- self.application = Application.builder().token(Config.TELEGRAM_BOT_TOKEN).drop_pending_updates(True).build()
|
|
|
+ # Create Updater for v13.x compatibility
|
|
|
+ # self.application is already initialized as Updater in __init__ if we move it there, or here.
|
|
|
+ # For consistency, let's ensure it's initialized if not already.
|
|
|
+ if not isinstance(self.application, Updater):
|
|
|
+ self.application = Updater(token=Config.TELEGRAM_BOT_TOKEN, use_context=True)
|
|
|
|
|
|
# Connect notification manager to the bot application
|
|
|
self.notification_manager.set_bot_application(self.application)
|
|
|
|
|
|
- # Set up handlers
|
|
|
+ # Set up handlers (handlers are added to dispatcher inside setup_handlers)
|
|
|
self.setup_handlers()
|
|
|
|
|
|
- keep_running_future = asyncio.Future() # Future to keep the bot alive
|
|
|
-
|
|
|
try:
|
|
|
- logger.info("🚀 Initializing bot application...")
|
|
|
- await self.application.initialize()
|
|
|
-
|
|
|
- logger.info(f"🚀 Starting Telegram trading bot v{self.version}...")
|
|
|
+ logger.info(f"🚀 Starting Telegram trading bot v{self.version} (v13.x mode)...")
|
|
|
|
|
|
- # Send startup notification
|
|
|
+ # Send startup notification (await is fine, send_message is async)
|
|
|
await self.send_message(
|
|
|
- f"🤖 <b>Manual Trading Bot v{self.version} Started</b>\n\n"
|
|
|
+ f"🤖 <b>Manual Trading Bot v{self.version} Started (v13.x mode)</b>\n\n"
|
|
|
f"✅ Connected to Hyperliquid {'Testnet' if Config.HYPERLIQUID_TESTNET else 'Mainnet'}\n"
|
|
|
f"📊 Default Symbol: {Config.DEFAULT_TRADING_TOKEN}\n"
|
|
|
f"🔄 All systems ready!\n\n"
|
|
|
"Use /start for quick actions or /help for all commands."
|
|
|
)
|
|
|
|
|
|
- # Start subsystems
|
|
|
+ # Start subsystems (market_monitor needs to be started as async)
|
|
|
+ # For v13, typically MarketMonitor might not be started with await here unless it's run in a separate async loop
|
|
|
+ # or if start_polling itself is managed within an asyncio context by the main script.
|
|
|
+ # Given trading_bot.py uses asyncio.run(), this should be okay.
|
|
|
await self.market_monitor.start()
|
|
|
|
|
|
- logger.info("▶️ Starting PTB application (handlers, dispatcher, polling...)...")
|
|
|
- await self.application.start() # This starts polling and other processes
|
|
|
+ logger.info("🔄 Starting PTB Updater polling (v13.x mode)...")
|
|
|
+ self.application.start_polling(drop_pending_updates=True)
|
|
|
|
|
|
- # logger.info(f"🔍 Type of self.application.running after start: {type(self.application.running)}") # NO LONGER NEEDED
|
|
|
- logger.info("Bot is now running. Awaiting external stop signal (e.g., Ctrl+C)...")
|
|
|
-
|
|
|
- # Wait indefinitely until an exception (like KeyboardInterrupt) or task cancellation
|
|
|
- await keep_running_future
|
|
|
+ logger.info("Bot is now running. Waiting for signals to stop (e.g., Ctrl+C)...")
|
|
|
+ self.application.idle() # This is blocking and handles signals
|
|
|
+ logger.info("PTB Updater has stopped/idled gracefully.")
|
|
|
|
|
|
except (KeyboardInterrupt, SystemExit):
|
|
|
logger.info("🛑 Bot run interrupted by user/system. Initiating shutdown...")
|
|
|
- if not keep_running_future.done():
|
|
|
- keep_running_future.set_exception(KeyboardInterrupt()) # Ensure future is resolved
|
|
|
- except asyncio.CancelledError:
|
|
|
- logger.info("🛑 Bot run task cancelled. Initiating shutdown...")
|
|
|
- if not keep_running_future.done():
|
|
|
- keep_running_future.cancel()
|
|
|
except Exception as e:
|
|
|
- logger.error(f"❌ Unhandled error in bot run loop: {e}", exc_info=True)
|
|
|
- if not keep_running_future.done():
|
|
|
- keep_running_future.set_exception(e)
|
|
|
+ logger.error(f"❌ Unhandled error in bot run loop (v13.x mode): {e}", exc_info=True)
|
|
|
finally:
|
|
|
- logger.info("🔌 Starting graceful shutdown sequence in TelegramTradingBot.run...")
|
|
|
+ logger.info("🔌 Starting graceful shutdown sequence in TelegramTradingBot.run (v13.x mode)...")
|
|
|
try:
|
|
|
logger.info("Stopping market monitor...")
|
|
|
await self.market_monitor.stop()
|
|
|
logger.info("Market monitor stopped.")
|
|
|
|
|
|
- if self.application:
|
|
|
- logger.info("Attempting to stop PTB application...")
|
|
|
- await self.application.stop()
|
|
|
- logger.info("PTB application stop attempted.")
|
|
|
-
|
|
|
- logger.info("Shutting down PTB application...")
|
|
|
- await self.application.shutdown()
|
|
|
- logger.info("PTB application shut down.")
|
|
|
- else:
|
|
|
- logger.warning("Application object was None during shutdown in TelegramTradingBot.run.")
|
|
|
+ if hasattr(self.application, 'running') and self.application.running:
|
|
|
+ logger.info("Stopping PTB Updater (v13.x mode)...")
|
|
|
+ self.application.stop()
|
|
|
+ logger.info("PTB Updater stopped.")
|
|
|
+ elif isinstance(self.application, Updater):
|
|
|
+ # If not `running` attribute, just call stop for Updater as a fallback.
|
|
|
+ logger.info("PTB Updater might not be running or attribute 'running' not found, attempting stop anyway...")
|
|
|
+ self.application.stop()
|
|
|
+ logger.info("PTB Updater stop attempted.")
|
|
|
|
|
|
- logger.info("✅ Graceful shutdown sequence in TelegramTradingBot.run complete.")
|
|
|
+ logger.info("✅ Graceful shutdown sequence in TelegramTradingBot.run (v13.x mode) complete.")
|
|
|
|
|
|
except Exception as e:
|
|
|
- logger.error(f"💥 Error during shutdown sequence in TelegramTradingBot.run: {e}", exc_info=True)
|
|
|
+ logger.error(f"💥 Error during shutdown sequence in TelegramTradingBot.run (v13.x mode): {e}", exc_info=True)
|