Browse Source

Add custom keyboard configuration for Telegram bot - Introduced options to enable/disable custom keyboard shortcuts and define a layout for persistent buttons. Enhanced bot functionality by allowing users to access commands quickly through a tailored keyboard interface.

Carles Sentis 4 days ago
parent
commit
e3004bcf3e
3 changed files with 62 additions and 2 deletions
  1. 11 0
      config/env.example
  2. 5 0
      src/config.py
  3. 46 2
      src/telegram_bot.py

+ 11 - 0
config/env.example

@@ -35,6 +35,17 @@ TELEGRAM_CHAT_ID=your_chat_id_here
 # Enable/disable Telegram integration
 TELEGRAM_ENABLED=true
 
+# ========================================
+# Custom Keyboard Configuration
+# ========================================
+# Enable/disable custom keyboard shortcuts (Freqtrade-style persistent buttons)
+TELEGRAM_CUSTOM_KEYBOARD_ENABLED=true
+
+# Custom keyboard layout - comma-separated commands per row, pipe-separated rows
+# Format: "cmd1,cmd2,cmd3|cmd4,cmd5|cmd6,cmd7,cmd8,cmd9"
+# Example: "/daily,/performance,/balance|/stats,/positions,/orders|/price,/market,/help,/commands"
+TELEGRAM_CUSTOM_KEYBOARD_LAYOUT="/daily,/performance,/balance|/stats,/positions,/orders|/price,/market,/help,/commands"
+
 # ========================================
 # Bot Monitoring Configuration
 # ========================================

+ 5 - 0
src/config.py

@@ -26,6 +26,10 @@ class Config:
     TELEGRAM_CHAT_ID: Optional[str] = os.getenv('TELEGRAM_CHAT_ID')
     TELEGRAM_ENABLED: bool = os.getenv('TELEGRAM_ENABLED', 'true').lower() == 'true'
     
+    # Custom Keyboard Configuration
+    TELEGRAM_CUSTOM_KEYBOARD_ENABLED: bool = os.getenv('TELEGRAM_CUSTOM_KEYBOARD_ENABLED', 'true').lower() == 'true'
+    TELEGRAM_CUSTOM_KEYBOARD_LAYOUT: str = os.getenv('TELEGRAM_CUSTOM_KEYBOARD_LAYOUT', '/daily,/performance,/balance|/stats,/positions,/orders|/price,/market,/help,/commands')
+    
     # Bot monitoring configuration
     BOT_HEARTBEAT_SECONDS = int(os.getenv('BOT_HEARTBEAT_SECONDS', '30'))
     
@@ -129,6 +133,7 @@ class Config:
         logger.info(f"  🔄 STOP_LOSS_PERCENTAGE: {cls.STOP_LOSS_PERCENTAGE}%")
         logger.info(f"  🤖 TELEGRAM_BOT_TOKEN: {'✅ Set' if cls.TELEGRAM_BOT_TOKEN else '❌ Not Set'}")
         logger.info(f"  💬 TELEGRAM_CHAT_ID: {'✅ Set' if cls.TELEGRAM_CHAT_ID else '❌ Not Set'}")
+        logger.info(f"  ⌨️ CUSTOM_KEYBOARD: {'✅ Enabled' if cls.TELEGRAM_CUSTOM_KEYBOARD_ENABLED else '❌ Disabled'}")
         logger.info(f"  🔍 LOG_FILE_PATH: {cls.LOG_FILE_PATH}")
         logger.info(f"  🔄 LOG_MAX_SIZE_MB: {cls.LOG_MAX_SIZE_MB} MB")
         logger.info(f"  🔄 LOG_BACKUP_COUNT: {cls.LOG_BACKUP_COUNT}")

+ 46 - 2
src/telegram_bot.py

@@ -11,7 +11,7 @@ import asyncio
 import re
 from datetime import datetime, timedelta
 from typing import Optional, Dict, Any
-from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
+from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup, ReplyKeyboardMarkup, KeyboardButton
 from telegram.ext import Application, CommandHandler, CallbackQueryHandler, ContextTypes, MessageHandler, filters
 from hyperliquid_client import HyperliquidClient
 from trading_stats import TradingStats
@@ -91,6 +91,34 @@ class TelegramTradingBot:
             except Exception as e:
                 logger.error(f"Failed to send message: {e}")
     
+    def _create_custom_keyboard(self) -> Optional[ReplyKeyboardMarkup]:
+        """Create a custom keyboard from configuration."""
+        if not Config.TELEGRAM_CUSTOM_KEYBOARD_ENABLED:
+            return None
+        
+        try:
+            layout = Config.TELEGRAM_CUSTOM_KEYBOARD_LAYOUT
+            # Parse the layout: "cmd1,cmd2,cmd3|cmd4,cmd5|cmd6,cmd7,cmd8,cmd9"
+            rows = layout.split('|')
+            keyboard = []
+            
+            for row in rows:
+                commands = [cmd.strip() for cmd in row.split(',') if cmd.strip()]
+                if commands:
+                    keyboard.append([KeyboardButton(cmd) for cmd in commands])
+            
+            if keyboard:
+                return ReplyKeyboardMarkup(
+                    keyboard,
+                    resize_keyboard=True,  # Resize to fit screen
+                    one_time_keyboard=False,  # Keep keyboard persistent
+                    selective=True  # Show only to authorized users
+                )
+        except Exception as e:
+            logger.error(f"Failed to create custom keyboard: {e}")
+        
+        return None
+    
     async def start_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
         """Handle the /start command."""
         if not self.is_authorized(update.effective_chat.id):
@@ -220,7 +248,23 @@ For support, contact your bot administrator.
         ]
         reply_markup = InlineKeyboardMarkup(keyboard)
         
-        await update.message.reply_text(welcome_text, parse_mode='HTML', reply_markup=reply_markup)
+        # Create custom keyboard for persistent buttons
+        custom_keyboard = self._create_custom_keyboard()
+        
+        # Send message with inline keyboard
+        await update.message.reply_text(
+            welcome_text, 
+            parse_mode='HTML', 
+            reply_markup=reply_markup
+        )
+        
+        # If custom keyboard is enabled, send a follow-up message to set the custom keyboard
+        if custom_keyboard:
+            await update.message.reply_text(
+                "⌨️ <b>Custom keyboard enabled!</b>\n\nUse the buttons below for quick access to commands:",
+                parse_mode='HTML',
+                reply_markup=custom_keyboard
+            )
     
     async def help_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
         """Handle the /help command."""