Просмотр исходного кода

Refactor TradingCommands to integrate InfoCommands and ManagementCommands - Updated the TradingCommands class to accept additional command handlers, enhancing command execution and user interaction. Improved button callback handling for better command processing and user feedback during interactions.

Carles Sentis 5 дней назад
Родитель
Сommit
73ca59941e
2 измененных файлов с 88 добавлено и 28 удалено
  1. 4 1
      src/bot/core.py
  2. 84 27
      src/commands/trading_commands.py

+ 4 - 1
src/bot/core.py

@@ -38,9 +38,12 @@ class TelegramTradingBot:
         self.market_monitor.set_notification_manager(self.notification_manager)
         
         # Initialize command handlers
-        self.trading_commands = TradingCommands(self.trading_engine, self.notification_manager)
         self.info_commands = InfoCommands(self.trading_engine)
         self.management_commands = ManagementCommands(self.trading_engine, self.market_monitor)
+        # Pass info and management command handlers to TradingCommands
+        self.trading_commands = TradingCommands(self.trading_engine, self.notification_manager, 
+                                              info_commands_handler=self.info_commands, 
+                                              management_commands_handler=self.management_commands)
         
     def is_authorized(self, chat_id: str) -> bool:
         """Check if the chat ID is authorized to use the bot."""

+ 84 - 27
src/commands/trading_commands.py

@@ -15,10 +15,12 @@ logger = logging.getLogger(__name__)
 class TradingCommands:
     """Handles all trading-related Telegram commands."""
     
-    def __init__(self, trading_engine, notification_manager):
-        """Initialize with trading engine and notification manager."""
+    def __init__(self, trading_engine, notification_manager, info_commands_handler=None, management_commands_handler=None):
+        """Initialize with trading engine, notification manager, and other command handlers."""
         self.trading_engine = trading_engine
         self.notification_manager = notification_manager
+        self.info_commands_handler = info_commands_handler
+        self.management_commands_handler = management_commands_handler
     
     def _is_authorized(self, chat_id: str) -> bool:
         """Check if the chat ID is authorized."""
@@ -472,7 +474,7 @@ This will place a limit {exit_side} order at ${stop_price:,.2f} to protect your
             elif position_type == "SHORT" and tp_price >= entry_price:
                 await context.bot.send_message(chat_id=chat_id, text=(
                     f"⚠️ Take profit price should be BELOW entry price for short positions\n\n"
-                    f"�� Your {token} SHORT position:\n"
+                    f"📊 Your {token} SHORT position:\n"
                     f"• Entry Price: ${entry_price:,.2f}\n"
                     f"• Take Profit: ${tp_price:,.2f} ❌\n\n"
                     f"💡 Try a lower price like: /tp {token} {entry_price * 0.95:.0f}"
@@ -588,31 +590,86 @@ This action cannot be undone.
             return
         
         callback_data = query.data
+        logger.info(f"Button callback triggered with data: {callback_data}")
+
+        # Define a map for informational and management command callbacks
+        # These commands expect `update` and `context` as if called by a CommandHandler
+        command_action_map = {}
+        if self.info_commands_handler:
+            command_action_map.update({
+                "balance": self.info_commands_handler.balance_command,
+                "positions": self.info_commands_handler.positions_command,
+                "orders": self.info_commands_handler.orders_command,
+                "stats": self.info_commands_handler.stats_command,
+                "price": self.info_commands_handler.price_command,
+                "market": self.info_commands_handler.market_command,
+                "performance": self.info_commands_handler.performance_command,
+                "daily": self.info_commands_handler.daily_command,
+                "weekly": self.info_commands_handler.weekly_command,
+                "monthly": self.info_commands_handler.monthly_command,
+                "trades": self.info_commands_handler.trades_command,
+                # Note: 'help' is handled separately below as its main handler is in TelegramTradingBot core
+            })
         
-        try:
-            if callback_data.startswith('confirm_long_'):
-                await self._execute_long_callback(query, callback_data)
-            elif callback_data.startswith('confirm_short_'):
-                await self._execute_short_callback(query, callback_data)
-            elif callback_data.startswith('confirm_exit_'):
-                await self._execute_exit_callback(query, callback_data)
-            elif callback_data.startswith('confirm_sl_'):
-                await self._execute_sl_callback(query, callback_data)
-            elif callback_data.startswith('confirm_tp_'):
-                await self._execute_tp_callback(query, callback_data)
-            elif callback_data.startswith('confirm_coo_'):
-                await self._execute_coo_callback(query, callback_data)
-            elif callback_data == 'cancel_order':
-                await query.edit_message_text("❌ Order cancelled.")
-            
-            # Handle info command button callbacks
-            elif callback_data in ['balance', 'positions', 'orders', 'stats', 'trades', 'market', 'price', 
-                                 'performance', 'daily', 'weekly', 'monthly', 'alarm', 'monitoring', 'logs', 'help']:
-                await query.edit_message_text(f"✅ Please use /{callback_data} command to get the latest data.")
-            
-        except Exception as e:
-            await query.edit_message_text(f"❌ Error processing order: {e}")
-            logger.error(f"Error in button callback: {e}")
+        if self.management_commands_handler:
+            command_action_map.update({
+                "alarm": self.management_commands_handler.alarm_command,
+                "monitoring": self.management_commands_handler.monitoring_command,
+                "logs": self.management_commands_handler.logs_command,
+                # Add other management commands here if they have quick action buttons
+            })
+
+        # Check if the callback_data matches a mapped informational/management command
+        if callback_data in command_action_map:
+            command_method = command_action_map[callback_data]
+            try:
+                logger.info(f"Executing {callback_data} command via button callback.")
+                # Edit the original message to indicate the action is being processed
+                # await query.edit_message_text(text=f"🔄 Processing {callback_data.capitalize()}...", parse_mode='HTML') # Optional
+                await command_method(update, context) # Call the actual command method
+                # After the command sends its own message(s), we might want to remove or clean up the original message with buttons.
+                # For now, let the command method handle all responses.
+                # Optionally, delete the message that had the buttons:
+                # await query.message.delete() 
+            except Exception as e:
+                logger.error(f"Error executing command '{callback_data}' from button: {e}", exc_info=True)
+                try:
+                    await query.message.reply_text(f"❌ Error processing {callback_data.capitalize()}: {e}")
+                except Exception as reply_e:
+                    logger.error(f"Failed to send error reply for {callback_data} button: {reply_e}")
+            return # Handled
+
+        # Special handling for 'help' callback from InfoCommands quick menu
+        if callback_data == "help":
+            logger.info("Handling 'help' button callback. Guiding user to /help command.")
+            try:
+                # Remove the inline keyboard from the original message and provide guidance.
+                await query.edit_message_text(
+                    text="📖 To view all commands and their descriptions, please type the /help command.",
+                    reply_markup=None, # Remove buttons
+                    parse_mode='HTML'
+                )
+            except Exception as e:
+                logger.error(f"Error editing message for 'help' callback: {e}")
+                # Fallback if edit fails (e.g., message too old)
+                await query.message.reply_text("📖 Please type /help for command details.", parse_mode='HTML')
+            return # Handled
+        
+        # Existing trading confirmation logic
+        if callback_data.startswith("confirm_long_"):
+            await self._execute_long_callback(query, callback_data)
+        elif callback_data.startswith("confirm_short_"):
+            await self._execute_short_callback(query, callback_data)
+        elif callback_data.startswith("confirm_exit_"):
+            await self._execute_exit_callback(query, callback_data)
+        elif callback_data.startswith("confirm_sl_"):
+            await self._execute_sl_callback(query, callback_data)
+        elif callback_data.startswith("confirm_tp_"):
+            await self._execute_tp_callback(query, callback_data)
+        elif callback_data.startswith("confirm_coo_"):
+            await self._execute_coo_callback(query, callback_data)
+        elif callback_data == 'cancel_order':
+            await query.edit_message_text("❌ Order cancelled.")
     
     async def _execute_long_callback(self, query, callback_data):
         """Execute long order from callback."""