Jelajahi Sumber

Enhance COPY command handling and update copy trading command structure

- Improved handling of the COPY command in TelegramTradingBot to allow direct execution without text modification.
- Updated the _handle_copy_status_keyboard method to use a mock context for better isolation of command execution.
- Refactored the copy start command to accept arguments directly, allowing for more flexible target address handling.
- Enhanced user feedback in command responses, clarifying the source of target addresses and improving overall command documentation.
Carles Sentis 5 hari lalu
induk
melakukan
0ae300dd97
3 mengubah file dengan 61 tambahan dan 37 penghapusan
  1. 23 11
      src/bot/core.py
  2. 37 25
      src/commands/copy_trading_commands.py
  3. 1 1
      trading_bot.py

+ 23 - 11
src/bot/core.py

@@ -212,11 +212,17 @@ class TelegramTradingBot:
 
         command_func = command_map.get(command_text)
         if command_func:
-            # We need to simulate a command call, so we'll prepend "/"
-            # to the message text to make it look like a real command.
-            original_text = update.message.text
-            update.message.text = f"/{original_text.lower()}"
-            await command_func(update, context)
+            # For COPY command, handle specially
+            if command_text == "COPY":
+                await command_func(update, context)
+            else:
+                # We need to simulate a command call, so we'll prepend "/"
+                # to the message text to make it look like a real command.
+                original_text = update.message.text
+                update.message.text = f"/{original_text.lower()}"
+                await command_func(update, context)
+                # Restore original text
+                update.message.text = original_text
         else:
             logger.warning(f"Unknown keyboard command: {command_text}")
             await self.notification_manager.send_generic_notification(
@@ -225,9 +231,15 @@ class TelegramTradingBot:
 
     async def _handle_copy_status_keyboard(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
         """Handle COPY keyboard command by showing copy trading status."""
-        # Set context.args to simulate /copy status
-        context.args = ["status"]
-        await self.copy_trading_cmds.copy_command(update, context)
+        # Create a mock context with status args to avoid modifying original
+        from types import SimpleNamespace
+        
+        # Create a simple object that mimics the context for copy commands
+        mock_context = SimpleNamespace()
+        mock_context.args = ["status"]
+        mock_context.bot = context.bot
+        
+        await self.copy_trading_cmds.copy_command(update, mock_context)
 
     async def start_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
         """Handle the /start command."""
@@ -302,9 +314,9 @@ class TelegramTradingBot:
 • /alarm 3 - Remove alarm ID 3
 
 <b>🔄 Copy Trading:</b>
-• /copy status - View copy trading status & session info
-• /copy start [address] - Start copying a target trader
-• /copy stop - Stop copy trading (preserves session)
+• /copy status - View copy trading status & configuration
+• /copy start [address] - Start copying a target trader's positions
+• /copy stop - Stop copy trading (session data preserved)
 
 <b>🔄 Automatic Monitoring:</b>
 • Real-time order fill alerts

+ 37 - 25
src/commands/copy_trading_commands.py

@@ -42,9 +42,9 @@ class CopyTradingCommands:
         if subcommand == "status":
             await self.copy_status_command(update, context)
         elif subcommand == "start":
-            # Pass remaining args (target address) to start command
-            context.args = context.args[1:]  # Remove 'start' from args
-            await self.copy_start_command(update, context)
+            # For start command, pass remaining args directly
+            start_args = context.args[1:] if len(context.args) > 1 else []
+            await self.copy_start_command_with_args(update, context, start_args)
         elif subcommand == "stop":
             await self.copy_stop_command(update, context)
         else:
@@ -64,11 +64,13 @@ class CopyTradingCommands:
 
 <b>Available Commands:</b>
 • <code>/copy status</code> - View copy trading status & session info
-• <code>/copy start [address]</code> - Start copying a target trader
+• <code>/copy start</code> - Start copying (uses config address)
+• <code>/copy start [address]</code> - Start copying a specific trader
 • <code>/copy stop</code> - Stop copy trading (preserves session)
 
 <b>Examples:</b>
 • <code>/copy status</code>
+• <code>/copy start</code> (uses COPY_TRADING_TARGET_ADDRESS from config)
 • <code>/copy start 0x1234567890abcdef1234567890abcdef12345678</code>
 • <code>/copy stop</code>
 
@@ -159,8 +161,8 @@ Use <code>/copy status</code> to check current status and configuration.
                 text=f"❌ Error retrieving copy trading status: {e}"
             )
     
-    async def copy_start_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
-        """Handle the /copy_start command."""
+    async def copy_start_command_with_args(self, update: Update, context: ContextTypes.DEFAULT_TYPE, args: list) -> None:
+        """Handle the /copy start command with specific arguments."""
         chat_id = update.effective_chat.id
         if not self._is_authorized(chat_id):
             await context.bot.send_message(chat_id=chat_id, text="❌ Unauthorized access.")
@@ -180,13 +182,16 @@ Use <code>/copy status</code> to check current status and configuration.
             if copy_monitor.enabled and copy_monitor.state_manager.is_enabled():
                 await context.bot.send_message(
                     chat_id=chat_id, 
-                    text="⚠️ Copy trading is already running. Use /copy_stop to stop it first."
+                    text="⚠️ Copy trading is already running. Use /copy stop to stop it first."
                 )
                 return
             
-            # Check if target address is provided
-            if context.args and len(context.args) > 0:
-                target_address = context.args[0]
+            # Determine target address - use config by default, override with argument if provided
+            target_address = None
+            
+            if args and len(args) > 0:
+                # Address provided as argument
+                target_address = args[0]
                 
                 # Validate Ethereum address format
                 if not target_address.startswith('0x') or len(target_address) != 42:
@@ -195,28 +200,35 @@ Use <code>/copy status</code> to check current status and configuration.
                         text="❌ Invalid Ethereum address format. Address must start with '0x' and be 42 characters long."
                     )
                     return
-                
-                # Update target address
-                copy_monitor.target_address = target_address
-                copy_monitor.config.COPY_TRADING_TARGET_ADDRESS = target_address
+            else:
+                # Use address from config
+                target_address = Config.COPY_TRADING_TARGET_ADDRESS
             
-            # Check if target address is set
-            if not copy_monitor.target_address:
+            # Check if target address is available
+            if not target_address:
                 await context.bot.send_message(
                     chat_id=chat_id, 
                     text=(
                         "❌ No target address configured.\n\n"
-                        "Usage: /copy_start [target_address]\n"
-                        "Example: /copy_start 0x1234567890abcdef1234567890abcdef12345678"
+                        "Either:\n"
+                        "• Set COPY_TRADING_TARGET_ADDRESS in your .env file, or\n"
+                        "• Provide address: /copy start [target_address]\n\n"
+                        "Example: /copy start 0x1234567890abcdef1234567890abcdef12345678"
                     )
                 )
                 return
             
+            # Update target address in monitor
+            copy_monitor.target_address = target_address
+            copy_monitor.config.COPY_TRADING_TARGET_ADDRESS = target_address
+            
             # Create confirmation message
+            address_source = "config file" if not args else "provided argument"
             message = f"""
 🚀 <b>Start Copy Trading Confirmation</b>
 
-🎯 <b>Target Trader:</b> <code>{copy_monitor.target_address}</code>
+🎯 <b>Target Trader:</b> <code>{target_address}</code>
+📍 <b>Address Source:</b> {address_source}
 💰 <b>Portfolio Allocation:</b> {copy_monitor.portfolio_percentage:.1%}
 📊 <b>Copy Mode:</b> {copy_monitor.copy_mode}
 ⚡ <b>Max Leverage:</b> {copy_monitor.max_leverage}x
@@ -234,7 +246,7 @@ This will:
             
             keyboard = [
                 [
-                    InlineKeyboardButton("✅ Start Copy Trading", callback_data=f"copy_start_confirm_{copy_monitor.target_address}"),
+                    InlineKeyboardButton("✅ Start Copy Trading", callback_data=f"copy_start_confirm_{target_address}"),
                     InlineKeyboardButton("❌ Cancel", callback_data="copy_cancel")
                 ]
             ]
@@ -298,7 +310,7 @@ This will:
 • Stop monitoring the target trader
 • Preserve session data for later resumption
 • Keep existing positions (won't auto-close)
-• You can restart later with /copy_start
+• You can restart later with /copy start
             """
             
             keyboard = [
@@ -342,8 +354,8 @@ This will:
                     text=(
                         "🚀 <b>Start Copy Trading</b>\n\n"
                         "Please provide the target trader's address:\n\n"
-                        "Usage: /copy_start [target_address]\n"
-                        "Example: /copy_start 0x1234567890abcdef1234567890abcdef12345678"
+                        "Usage: /copy start [target_address]\n"
+                        "Example: /copy start 0x1234567890abcdef1234567890abcdef12345678"
                     ),
                     parse_mode='HTML'
                 )
@@ -366,7 +378,7 @@ This will:
                         f"✅ Copy trading started!\n\n"
                         f"🎯 Target: {target_address[:10]}...\n"
                         f"📊 Monitoring active positions and new trades\n\n"
-                        f"Use /copy_status to check progress.",
+                        f"Use /copy status to check progress.",
                         parse_mode='HTML'
                     )
                 else:
@@ -381,7 +393,7 @@ This will:
                     await query.edit_message_text(
                         "✅ Copy trading stopped!\n\n"
                         "📊 Session data preserved\n"
-                        "🔄 Use /copy_start to resume later",
+                        "🔄 Use /copy start to resume later",
                         parse_mode='HTML'
                     )
                 else:

+ 1 - 1
trading_bot.py

@@ -14,7 +14,7 @@ from datetime import datetime
 from pathlib import Path
 
 # Bot version
-BOT_VERSION = "3.0.321"
+BOT_VERSION = "3.0.322"
 
 # Add src directory to Python path
 sys.path.insert(0, str(Path(__file__).parent / "src"))