Skip to content

Commit ad9923b

Browse files
committed
Add BackButton...
It's gross but it works?
1 parent c21d99c commit ad9923b

File tree

2 files changed

+35
-7
lines changed

2 files changed

+35
-7
lines changed

examples/menubot.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88

99
import telegram.ext
1010
from telegram.ext import CommandHandler
11-
from telegram.ext.menu import Menu, MenuHandler, Button
11+
from telegram.ext.menu import Menu, MenuHandler, Button, BackButton
1212

1313
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
1414
level=logging.DEBUG)
1515

1616
logger = logging.getLogger(__name__)
1717

18-
updater = telegram.ext.Updater('TOKEN')
18+
updater = telegram.ext.Updater('225497476:AAGzbYE3aAYJFmOtRNqIL0qEBisdzx2xdSc')
1919
dp = updater.dispatcher
2020

2121

@@ -46,7 +46,7 @@ def buttons(self):
4646
return [
4747
# [ToggleButton('Toggleable', 'on'), ToggleButton('Toggleable', 'on')],
4848
[Button('Recursion', menu=SubMenu1), Button('Other menu!', menu=SubMenu2)],
49-
[Button('Back to main menu', menu=MainMenu)] # [BackButton('Back')]
49+
[BackButton('Back')]
5050
]
5151

5252

@@ -56,7 +56,7 @@ class SubMenu2(Menu):
5656
buttons = [
5757
[Button('Start', start), Button('URL', url='https://google.com')],
5858
# [RadioButton('Option1', 1, group=1), RadioButton('Option2', 2, group=1)],
59-
[Button('Back to main menu', menu=MainMenu)] # [BackButton('Back')]
59+
[BackButton('Back')]
6060
]
6161

6262
dp.add_handler(MenuHandler(MainMenu))

telegram/ext/menu.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@
1818
# along with this program. If not, see [http://www.gnu.org/licenses/].
1919
"""This module contains objects helps with creating menus for telegram bots."""
2020

21-
# pylint: disable=undefined-variable, not-callable
21+
# pylint: disable=not-callable
2222

2323
import uuid
24+
from collections import defaultdict
2425
from itertools import chain
2526

2627
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
@@ -30,7 +31,7 @@
3031
try:
3132
str_type = str
3233
except NameError:
33-
str_type = basestring # noqa
34+
str_type = basestring # noqa pylint: disable=undefined-variable
3435

3536

3637
class Menu(object):
@@ -39,13 +40,18 @@ class Menu(object):
3940
text = ''
4041
buttons = None
4142
data = {}
43+
root_menu = None # populated in menuhandler
44+
stack = None # Only used in root menu assigned in menuhandler
4245

4346
def __new__(cls):
4447
if not cls._instance:
4548
cls._instance = super(Menu, cls).__new__(cls)
4649
return cls._instance
4750

4851
def callback(self, bot, update, user_data, chat_data):
52+
_id = (update.callback_query.message.chat_id, update.callback_query.message.message_id
53+
) if update.callback_query.message else update.callback_query.inline_message_id
54+
self.root_menu().stack[_id].append(self)
4955
try:
5056
return update.callback_query.edit_message_text(self.get_text(update),
5157
reply_markup=self.keyboard(user_data,
@@ -70,7 +76,7 @@ def keyboard(self, user_data, chat_data):
7076
def get_buttons(self):
7177
if self._buttons is None:
7278
if callable(self.buttons):
73-
self._buttons = self.buttons()
79+
self._buttons = self.buttons() # noqa
7480
else:
7581
self._buttons = self.buttons
7682
return self._buttons
@@ -119,6 +125,7 @@ def __init__(self,
119125
self.name = str(uuid.uuid4())
120126

121127
self.parent_menu = None
128+
self.root_menu = None
122129

123130
super(Button, self).__init__(
124131
pass_update_queue=pass_update_queue,
@@ -145,19 +152,40 @@ def text(self, user_data, chat_data):
145152
return self._text
146153

147154

155+
class BackButton(Button):
156+
def __init__(self, text, name=None):
157+
super(BackButton, self).__init__(text, callback=self._callback,
158+
pass_user_data=True, pass_chat_data=True, name=name)
159+
160+
def _callback(self, bot, update, user_data, chat_data):
161+
_id = (update.callback_query.message.chat_id, update.callback_query.message.message_id
162+
) if update.callback_query.message else update.callback_query.inline_message_id
163+
164+
stack = self.parent_menu().root_menu().stack[_id]
165+
try:
166+
stack.pop()
167+
last_menu = stack.pop()
168+
except IndexError:
169+
last_menu = self.parent_menu().root_menu()
170+
last_menu.callback(bot, update, user_data, chat_data)
171+
172+
148173
class MenuHandler(Handler):
149174
def __init__(self, menu):
150175
self.menu = menu
151176
self.buttons = {}
152177
self.collect_buttons(self.menu)
153178

179+
menu.stack = defaultdict(list)
180+
154181
super(MenuHandler, self).__init__(
155182
pass_update_queue=None,
156183
pass_job_queue=None,
157184
pass_user_data=None,
158185
pass_chat_data=None)
159186

160187
def collect_buttons(self, menu):
188+
menu.root_menu = self.menu
161189
for button in chain.from_iterable(menu().get_buttons()):
162190
button.parent_menu = menu
163191
if button.name not in self.buttons and (button.callback is not None or

0 commit comments

Comments
 (0)