Explorar o código

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 hai 5 días
pai
achega
73ca59941e
Modificáronse 2 ficheiros con 88 adicións e 28 borrados
  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."""