Skip to content

Commit 493b7c0

Browse files
committed
Use factory pattern instead + merge master.
1 parent 1b66b72 commit 493b7c0

File tree

2 files changed

+67
-61
lines changed

2 files changed

+67
-61
lines changed

examples/menubot.py

Lines changed: 46 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
#!/usr/bin/env python
22
# -*- coding: utf-8 -*-
33
#
4-
# Simple Bot to reply to Telegram messages
4+
# Sample bot to show proof of concept menu system
55
# This program is dedicated to the public domain under the CC0 license.
66

77
import logging
88

99
import telegram.ext
1010
from telegram.ext import CommandHandler
11-
from telegram.ext.menu import Menu, MenuHandler, Button, BackButton, ToggleButton, RadioButton
11+
from telegram.ext.menu import MenuHandler, Button, BackButton, ToggleButton, RadioButton, \
12+
make_menu
1213

1314
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
1415
level=logging.DEBUG)
1516

1617
logger = logging.getLogger(__name__)
1718

18-
updater = telegram.ext.Updater('225497476:AAGzbYE3aAYJFmOtRNqIL0qEBisdzx2xdSc')
19+
updater = telegram.ext.Updater('225497476:AAFHMga1uS470y49vUxyutvUbpyZXxnvvnQ')
1920
dp = updater.dispatcher
2021

2122

@@ -24,7 +25,6 @@ def error(bot, update, e):
2425

2526

2627
def start(bot, update):
27-
update.callback_query.answer()
2828
update.effective_message.reply_text('Hello!')
2929

3030

@@ -33,55 +33,48 @@ def submit(bot, update, menu_data):
3333
update.effective_message.reply_text(str(menu_data))
3434

3535

36-
class MainMenu(Menu):
37-
def text(self, update):
38-
return 'Hello {}. This is the main menu!'.format(update.effective_user.first_name)
39-
40-
def buttons(self):
41-
return [
42-
[Button('Test', menu=sub_menu1), Button('Test2', menu=sub_menu2)],
43-
[Button('Exit', callback=start)]
44-
]
45-
46-
47-
class SubMenu1(Menu):
48-
text = 'This is sub menu 1'
49-
50-
def buttons(self):
51-
return [
52-
[Button('URL', url='https://google.com')],
53-
[Button('Recursion', menu=sub_menu1), Button('Other menu!', menu=sub_menu2)],
54-
[BackButton('Back')]
55-
]
56-
57-
58-
class SubMenu2(Menu):
59-
text = 'This is sub menu 2'
60-
61-
buttons = [
62-
[
63-
ToggleButton('test', 'Test'),
64-
ToggleButton('count', states=((1, '1'), (2, '2'), (3, '3')), default=2)
65-
],
66-
[
67-
RadioButton('options', 1, 'Option 1'),
68-
RadioButton('options', 2, 'Option 2', enabled=True),
69-
RadioButton('options', 3, 'Option 3')
70-
],
71-
[
72-
RadioButton('custom', 1, ('[ ] Custom', '[x] Custom')),
73-
RadioButton('custom', 2, ('[ ] Custom 2', '[x] Custom 2'), enabled=True)
74-
],
75-
[
76-
Button('Submit', submit, pass_menu_data=True),
77-
BackButton('Back')
78-
]
79-
]
80-
81-
82-
main_menu = MainMenu()
83-
sub_menu1 = SubMenu1()
84-
sub_menu2 = SubMenu2()
36+
main_menu = make_menu('main', lambda update: 'Hello {}. This is the main menu!'.format(
37+
update.effective_user.first_name), buttons=lambda update: [
38+
[Button('Test', menu=sub_menu1), Button('Test2', menu=sub_menu2)]
39+
])
40+
41+
42+
def sub_menu1_buttons(update):
43+
# NOTE: Doesn't work yet... This is because telegram doesn't send language_code for other
44+
# than messages. this means we are required to safe that data when we first get a message
45+
# and then use it afterwards. But menus don't currently pass user_data. Waiting for #1080
46+
lang_default = 'en_GB'
47+
if update and update.effective_user.language_code:
48+
lang_default = update.effective_user.language_code
49+
return [
50+
[Button('URL', url='https://google.com')],
51+
[Button('Recursion', menu=sub_menu1), Button('Other menu!', menu=sub_menu2)],
52+
[ToggleButton('lang', states=(('en_GB', 'English (GB)'), ('en_US', 'English (US)')),
53+
default=lang_default)],
54+
[BackButton('Back')]
55+
]
56+
57+
58+
sub_menu1 = make_menu('sub_1', 'This is sub menu 1', buttons=sub_menu1_buttons)
59+
sub_menu2 = make_menu('sub_2', 'This is sub menu 2', buttons=[
60+
[
61+
ToggleButton('test', 'Test'),
62+
ToggleButton('count', states=((1, '1'), (2, '2'), (3, '3')), default=2)
63+
],
64+
[
65+
RadioButton('options', 1, 'Option 1'),
66+
RadioButton('options', 2, 'Option 2', enabled=True),
67+
RadioButton('options', 3, 'Option 3')
68+
],
69+
[
70+
RadioButton('custom', 1, ('[ ] Custom', '[x] Custom')),
71+
RadioButton('custom', 2, ('[ ] Custom 2', '[x] Custom 2'), enabled=True)
72+
],
73+
[
74+
Button('Submit', submit, pass_menu_data=True),
75+
BackButton('Back')
76+
]
77+
])
8578

8679
dp.add_handler(MenuHandler(main_menu))
8780
dp.add_handler(CommandHandler('menu', main_menu.start))

telegram/ext/menu.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,9 @@
1717
# You should have received a copy of the GNU Lesser Public License
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."""
20-
21-
from uuid import uuid4
2220
from collections import defaultdict, OrderedDict
2321
from itertools import chain
22+
from uuid import uuid4
2423

2524
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
2625
from telegram.error import BadRequest
@@ -44,8 +43,8 @@ class Menu(object):
4443
buttons = None
4544
data = None
4645
default_data = None
47-
root_menu = None # populated in menuhandler
48-
stack = None # Only used in root menu assigned in menuhandler
46+
root_menu = None # Populated in MenuHandler
47+
stack = None # Only used in root menu assigned in MenuHandler
4948

5049
def callback(self, bot, update, add_to_stack=True):
5150
if add_to_stack:
@@ -67,12 +66,12 @@ def start(self, bot, update):
6766

6867
def keyboard(self, update):
6968
return InlineKeyboardMarkup([[x.keyboard_button(update) for x in y] for y in
70-
self.get_buttons()]) # noqa
69+
self.get_buttons(update)]) # noqa
7170

72-
def get_buttons(self):
71+
def get_buttons(self, update):
7372
if self._buttons is None:
7473
if callable(self.buttons):
75-
self._buttons = self.buttons() # noqa pylint: disable=not-callable
74+
self._buttons = self.buttons(update) # noqa pylint: disable=not-callable
7675
else:
7776
self._buttons = self.buttons
7877
return self._buttons
@@ -265,7 +264,7 @@ def __init__(self, menu):
265264

266265
def collect_buttons(self, menu):
267266
menu.root_menu = self.menu
268-
for button in chain.from_iterable(menu.get_buttons()):
267+
for button in chain.from_iterable(menu.get_buttons(None)):
269268
button.parent_menu = menu
270269
button.post_init()
271270
if button.uuid not in self.buttons and (button.callback is not None or
@@ -280,3 +279,17 @@ def check_update(self, update):
280279
def handle_update(self, update, dispatcher):
281280
# Let the button handle it
282281
return self.buttons[update.callback_query.data].handle_update(update, dispatcher)
282+
283+
284+
def make_menu(name, text, buttons):
285+
if callable(text):
286+
def _text(self, update):
287+
return text(update)
288+
else:
289+
_text = text
290+
if callable(buttons):
291+
def _buttons(self, update):
292+
return buttons(update)
293+
else:
294+
_buttons = buttons
295+
return type(name, (Menu,), dict(text=_text, buttons=_buttons))()

0 commit comments

Comments
 (0)