Ver Fonte

Refactor TradingCommands initialization and enhance command handling - Updated the TradingCommands class to accept instances of InfoCommands and ManagementCommands, along with the bot instance itself, for improved command execution. Enhanced button callback handling to streamline command processing and provide user feedback during interactions.

Carles Sentis há 5 dias atrás
pai
commit
1e0cf4d47d
2 ficheiros alterados com 106 adições e 9 exclusões
  1. 8 1
      src/bot/core.py
  2. 98 8
      src/commands/trading_commands.py

+ 8 - 1
src/bot/core.py

@@ -38,9 +38,16 @@ 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_commands, management_commands, and the bot instance (self) to TradingCommands
+        self.trading_commands = TradingCommands(
+            self.trading_engine, 
+            self.notification_manager, 
+            self.info_commands, 
+            self.management_commands,
+            self # Pass the TelegramTradingBot instance itself
+        )
         
     def is_authorized(self, chat_id: str) -> bool:
         """Check if the chat ID is authorized to use the bot."""

+ 98 - 8
src/commands/trading_commands.py

@@ -15,10 +15,13 @@ 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_instance, management_commands_instance, telegram_bot_instance):
+        """Initialize with trading engine, notification manager, and other command instances."""
         self.trading_engine = trading_engine
         self.notification_manager = notification_manager
+        self.info_commands_instance = info_commands_instance
+        self.management_commands_instance = management_commands_instance
+        self.telegram_bot_instance = telegram_bot_instance
     
     def _is_authorized(self, chat_id: str) -> bool:
         """Check if the chat ID is authorized."""
@@ -472,7 +475,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}"
@@ -589,6 +592,41 @@ This action cannot be undone.
         
         callback_data = query.data
         
+        # Prepare a dictionary to map callback_data to command handlers
+        # The command handlers expect an Update object and a Context object
+        
+        # Create a mock Update object based on the query for command handlers
+        # The command handlers usually expect update.message to be present
+        # and context.args for commands that take arguments (not needed for these simple buttons)
+        
+        # Command map for info and management commands
+        # These commands are simple and don't typically require args from buttons
+        command_map = {
+            "balance": self.info_commands_instance.balance_command,
+            "positions": self.info_commands_instance.positions_command,
+            "orders": self.info_commands_instance.orders_command,
+            "stats": self.info_commands_instance.stats_command,
+            "trades": self.info_commands_instance.trades_command,
+            "market": self.info_commands_instance.market_command,
+            "price": self.info_commands_instance.price_command,
+            "performance": self.info_commands_instance.performance_command,
+            "daily": self.info_commands_instance.daily_command,
+            "weekly": self.info_commands_instance.weekly_command,
+            "monthly": self.info_commands_instance.monthly_command,
+            "risk": self.info_commands_instance.risk_command,
+            "balance_adjustments": self.info_commands_instance.balance_adjustments_command,
+            "commands": self.info_commands_instance.commands_command,
+            # Management commands
+            "monitoring": self.management_commands_instance.monitoring_command,
+            "alarm": self.management_commands_instance.alarm_command,
+            "logs": self.management_commands_instance.logs_command,
+            "debug": self.management_commands_instance.debug_command,
+            "version": self.management_commands_instance.version_command,
+            "keyboard": self.management_commands_instance.keyboard_command,
+            # Help command handled by the main bot instance
+            "help": self.telegram_bot_instance.help_command
+        }
+
         try:
             if callback_data.startswith('confirm_long_'):
                 await self._execute_long_callback(query, callback_data)
@@ -605,11 +643,63 @@ This action cannot be undone.
             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.")
-            
+            # Handle info and management command button callbacks by direct execution
+            elif callback_data in command_map:
+                # For these simple button commands, context.args is typically empty.
+                # The original message (query.message) is used as the basis for the Update object.
+                # Some commands might expect `update.effective_chat.id` or similar from the Update object.
+                # query.message should provide `chat.id`.
+                # We need to ensure `context.args` is empty or not accessed by these simple commands.
+                # Most of these commands (e.g. balance, positions) don't use context.args when called via slash commands without args.
+                
+                # Create a new Update object that the command handlers expect.
+                # The crucial part is that `update.message` (or `update.effective_message`) is available.
+                # And `update.effective_chat.id` can be derived.
+                # For commands that might send a new message, they need context.bot.
+                
+                # Edit the message to indicate the action is being processed, then call the command.
+                # This provides immediate feedback to the user.
+                button_text = query.message.reply_markup.inline_keyboard[0][0].text # Attempt to get button text for feedback
+                for row in query.message.reply_markup.inline_keyboard:
+                    for button in row:
+                        if button.callback_data == callback_data:
+                            button_text = button.text
+                            break
+                    if button_text != query.message.reply_markup.inline_keyboard[0][0].text: # check if found
+                        break
+                
+                await query.edit_message_text(f"⏳ Processing '{button_text}'...") # Feedback
+
+                # Construct an Update object that mimics one from a CommandHandler
+                # Ensure context.args is empty for these parameter-less commands
+                current_context_args = context.args
+                context.args = [] # Temporarily set args to empty for these button calls
+                
+                command_handler_update = Update(
+                    update_id=query.update_id, 
+                    message=query.message # Command handlers expect update.message or update.effective_message
+                    # callback_query=query # Some handlers might inspect this, but usually not for simple commands
+                )
+                # Ensure effective_chat is set correctly for the command handler
+                if command_handler_update.message:
+                     command_handler_update.effective_chat = command_handler_update.message.chat
+
+
+                await command_map[callback_data](command_handler_update, context)
+                
+                context.args = current_context_args # Restore context.args
+
+
+                # After the command executes, it might have sent its own messages.
+                # We might want to remove the "Processing..." message or the keyboard.
+                # For now, let's assume the command itself handles the output.
+                # Optionally, delete the "Processing..." message if the command sends a new one.
+                # await query.delete_message() # Or query.edit_message_text("✅ Done.") if command doesn't send a message.
+
+            else:
+                logger.warning(f"Unhandled callback_data: {callback_data}")
+                await query.edit_message_text(f"❓ Unknown action: {callback_data}. Please try again or use a command.")
+
         except Exception as e:
             await query.edit_message_text(f"❌ Error processing order: {e}")
             logger.error(f"Error in button callback: {e}")