The Telegram Manager Bot has been refactored to use Reply Keyboard Buttons instead of inline callback buttons. This provides a more traditional and user-friendly Telegram interface with persistent keyboard menus.
# Added Telethon reply keyboard types
from telethon.tl.types import ReplyKeyboardMarkup, KeyboardButtonReplaced callback-based constants with button text labels:
Before (Inline Buttons):
CLOSE_FULL = "close_full"
CLOSE_HALF = "close_half"
REFRESH = "refresh"After (Reply Buttons):
CMD_CLOSE_FULL = "🔴 Close Full"
CMD_CLOSE_HALF = "🟡 Close Half"
CMD_REFRESH = "🔄 Refresh"
CMD_BACK = "⬅️ Back"Added user state tracking for multi-step interactions:
# User state tracking
self.user_states: Dict[int, Dict] = {} # user_id -> {state, context}
self.current_positions: Dict[int, List] = {} # user_id -> positions list
# States
STATE_MAIN_MENU = "main_menu"
STATE_POSITION_MENU = "position_menu"
STATE_VIEWING_POSITION = "viewing_position"
STATE_AWAITING_SL = "awaiting_sl"Added two new methods to generate reply keyboards:
def _get_main_menu_keyboard(self):
"""Create main menu reply keyboard"""
buttons = [
[KeyboardButton('📊 Active Positions'), KeyboardButton('📋 Signals')],
[KeyboardButton('❓ Help')]
]
return ReplyKeyboardMarkup(buttons, resize_keyboard=True, single_use=False)
def _get_position_menu_keyboard(self, ticket: int):
"""Create position action reply keyboard"""
buttons = [
[KeyboardButton(self.CMD_CLOSE_FULL), KeyboardButton(self.CMD_CLOSE_HALF)],
[KeyboardButton(self.CMD_RISK_FREE), KeyboardButton(self.CMD_REFRESH)],
[KeyboardButton(self.CMD_UPDATE_SL), KeyboardButton(self.CMD_SAVE_PROFIT)],
[KeyboardButton(self.CMD_BACK)]
]
return ReplyKeyboardMarkup(buttons, resize_keyboard=True, single_use=False)Removed handle_callback() method - no longer needed for inline buttons.
The start() method now only registers:
self.client.on(events.NewMessage())(self.handle_message)Complete rewrite to handle button text instead of callback queries:
async def handle_message(self, event):
"""Handle incoming messages and keyboard button presses"""
# Get user state
user_state = self.user_states.get(user_id, {})
current_state = user_state.get('state', self.STATE_MAIN_MENU)
# Match button text instead of callback data
if message_text == '📊 Active Positions':
await self.cmd_active_positions(event)
elif message_text == self.CMD_CLOSE_FULL:
await self._action_close_full(event, ticket)
# ... etc# Before: Returned tuple with buttons
def _format_position_live(self, position) -> Tuple[str, List[Tuple[str, str]]]:
return pos_text, buttons
# After: Returns only formatted text
def _format_position_live(self, position) -> str:
return pos_textAll action handlers now use reply messages instead of callback answers:
# Before:
await event.answer("✅ Position closed")
await event.edit("✅ **Position Closed Successfully**")
# After:
keyboard = self._get_main_menu_keyboard()
await event.reply("✅ **Position Closed Successfully**\n\nSelect another action...",
parse_mode='md', buttons=keyboard)- Main Menu Navigation: Easy return to main menu from any state with "⬅️ Back" button
- Persistent Keyboards: Keyboards stay visible for multiple actions
- State Management: Track user interactions for context-aware responses
- Multi-position Handling: First position with action buttons, others listed below
- Buttons disappeared after interaction
- Required callback parsing
- Limited to inline layouts
- No persistent navigation
✅ Persistent keyboard menus ✅ Natural button text labels with emojis ✅ Easy main menu access with "Back" button ✅ Multi-step interactions with state tracking ✅ Better mobile UX ✅ More intuitive navigation
┌─────────────────────────────────────┐
│ 📊 Active Positions │ 📋 Signals │
├─────────────────────────────────────┤
│ ❓ Help │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ 🔴 Close Full │ 🟡 Close Half │
├─────────────────────────────────────┤
│ 🟢 Risk Free │ 🔄 Refresh │
├─────────────────────────────────────┤
│ 📈 Update SL │ 💰 Save Profit │
├─────────────────────────────────────┤
│ ⬅️ Back │
└─────────────────────────────────────┘
- All
/commandsstill work (/start,/active,/signals,/help) manager_chat_idsstill supported for initializationallowed_userswhitelist still controls access
- Settings configuration unchanged
from_settings()method unchanged- MetaTrader integration unchanged
- Database signal fetching unchanged
| Metric | Value |
|---|---|
| Lines Updated | ~150 |
| New Methods | 3 |
| Removed Methods | 1 |
| Files Modified | 1 |
| Callback Handlers | 0 (was 8) |
-
/startcommand shows main menu - Main menu buttons work correctly
- "📊 Active Positions" displays positions
- Action buttons appear for first position
- "🔴 Close Full" closes position
- "🟡 Close Half" closes half
- "🟢 Risk Free" sets to entry price
- "🔄 Refresh" updates position data
- "📈 Update SL" prompts for new SL
- "💰 Save Profit" executes profit taking
- "⬅️ Back" returns to main menu
- "📋 Signals" shows historical signals
- "❓ Help" shows help message
- Multiple users can use bot concurrently
-
allowed_userswhitelist works
- Inline Menus for Large Position Lists: Use inline pagination for many positions
- Quick Actions: Shortcut buttons for common actions
- Settings Menu: Allow users to configure preferences
- Position Filtering: Filter by symbol, type, or profit/loss
- Notifications: Alert users when certain thresholds are hit
- Multi-Language Support: Localize keyboard text