Skip to content

Commit ad3eec2

Browse files
authored
ConversationHandler (python-telegram-bot#331)
* initial commit for conversationhandler and example * implement simple Promise for run_async/conversationhandler * refactor Promise._done to done * add handling for timed out Promises * correctly handle promises with None results * fix handling tuple states * update comments on example * Added a first test on the ConversationHandler. * Fixed a small typo. * Yapf'd. * add sphinx doc for conversation handler * fix title for callbackqueryhandler sphinx docs
1 parent e3fe1d2 commit ad3eec2

19 files changed

+625
-20
lines changed
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
telegram.ext.handler module
2-
===========================
1+
telegram.ext.callbackqueryhandler module
2+
========================================
33

4-
.. automodule:: telegram.ext.handler
4+
.. automodule:: telegram.ext.callbackqueryhandler
55
:members:
66
:undoc-members:
77
:show-inheritance:
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
telegram.ext.conversationhandler module
2+
=======================================
3+
4+
.. automodule:: telegram.ext.conversationhandler
5+
:members:
6+
:undoc-members:
7+
:show-inheritance:

docs/source/telegram.ext.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Submodules
1111
telegram.ext.jobqueue
1212
telegram.ext.handler
1313
telegram.ext.choseninlineresulthandler
14+
telegram.ext.conversationhandler
1415
telegram.ext.commandhandler
1516
telegram.ext.inlinequeryhandler
1617
telegram.ext.messagehandler

examples/conversationbot.py

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
#
4+
# Simple Bot to reply to Telegram messages
5+
# This program is dedicated to the public domain under the CC0 license.
6+
"""
7+
This Bot uses the Updater class to handle the bot.
8+
9+
First, a few callback functions are defined. Then, those functions are passed to
10+
the Dispatcher and registered at their respective places.
11+
Then, the bot is started and runs until we press Ctrl-C on the command line.
12+
13+
Usage:
14+
Example of a bot-user conversation using ConversationHandler.
15+
Send /start to initiate the conversation.
16+
Press Ctrl-C on the command line or send a signal to the process to stop the
17+
bot.
18+
"""
19+
20+
from telegram import (ReplyKeyboardMarkup)
21+
from telegram.ext import (Updater, CommandHandler, MessageHandler, Filters, RegexHandler,
22+
ConversationHandler)
23+
24+
import logging
25+
26+
# Enable logging
27+
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
28+
level=logging.INFO)
29+
30+
logger = logging.getLogger(__name__)
31+
32+
GENDER, PHOTO, LOCATION, BIO = range(4)
33+
34+
35+
def start(bot, update):
36+
reply_keyboard = [['Boy', 'Girl', 'Other']]
37+
38+
bot.sendMessage(update.message.chat_id,
39+
text='Hi! My name is Professor Bot. I will hold a conversation with you. '
40+
'Send /cancel to stop talking to me.\n\n'
41+
'Are you a boy or a girl?',
42+
reply_markup=ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True))
43+
44+
return GENDER
45+
46+
47+
def gender(bot, update):
48+
user = update.message.from_user
49+
logger.info("Gender of %s: %s" % (user.first_name, update.message.text))
50+
bot.sendMessage(update.message.chat_id,
51+
text='I see! Please send me a photo of yourself, '
52+
'so I know what you look like, or send /skip if you don\'t want to.')
53+
54+
return PHOTO
55+
56+
57+
def photo(bot, update):
58+
user = update.message.from_user
59+
photo_file = bot.getFile(update.message.photo[-1].file_id)
60+
photo_file.download('user_photo.jpg')
61+
logger.info("Photo of %s: %s" % (user.first_name, 'user_photo.jpg'))
62+
bot.sendMessage(update.message.chat_id, text='Gorgeous! Now, send me your location please, '
63+
'or send /skip if you don\'t want to.')
64+
65+
return LOCATION
66+
67+
68+
def skip_photo(bot, update):
69+
user = update.message.from_user
70+
logger.info("User %s did not send a photo." % user.first_name)
71+
bot.sendMessage(update.message.chat_id, text='I bet you look great! Now, send me your '
72+
'location please, or send /skip.')
73+
74+
return LOCATION
75+
76+
77+
def location(bot, update):
78+
user = update.message.from_user
79+
user_location = update.message.location
80+
logger.info("Location of %s: %f / %f"
81+
% (user.first_name, user_location.latitude, user_location.longitude))
82+
bot.sendMessage(update.message.chat_id, text='Maybe I can visit you sometime! '
83+
'At last, tell me something about yourself.')
84+
85+
return BIO
86+
87+
88+
def skip_location(bot, update):
89+
user = update.message.from_user
90+
logger.info("User %s did not send a location." % user.first_name)
91+
bot.sendMessage(update.message.chat_id, text='You seem a bit paranoid! '
92+
'At last, tell me something about yourself.')
93+
94+
return BIO
95+
96+
97+
def bio(bot, update):
98+
user = update.message.from_user
99+
logger.info("Bio of %s: %s" % (user.first_name, update.message.text))
100+
bot.sendMessage(update.message.chat_id,
101+
text='Thank you! I hope we can talk again some day.')
102+
103+
return ConversationHandler.END
104+
105+
106+
def cancel(bot, update):
107+
user = update.message.from_user
108+
logger.info("User %s canceled the conversation." % user.first_name)
109+
bot.sendMessage(update.message.chat_id,
110+
text='Bye! I hope we can talk again some day.')
111+
112+
return ConversationHandler.END
113+
114+
115+
def error(bot, update, error):
116+
logger.warn('Update "%s" caused error "%s"' % (update, error))
117+
118+
119+
def main():
120+
# Create the EventHandler and pass it your bot's token.
121+
updater = Updater("TOKEN")
122+
123+
# Get the dispatcher to register handlers
124+
dp = updater.dispatcher
125+
126+
# Add conversation handler with the states GENDER, PHOTO, LOCATION and BIO
127+
conv_handler = ConversationHandler(
128+
entry_points=[CommandHandler('start', start)],
129+
130+
states={
131+
GENDER: [RegexHandler('^(Boy|Girl|Other)$', gender)],
132+
133+
PHOTO: [MessageHandler([Filters.photo], photo),
134+
CommandHandler('skip', skip_photo)],
135+
136+
LOCATION: [MessageHandler([Filters.location], location),
137+
CommandHandler('skip', skip_location)],
138+
139+
BIO: [MessageHandler([Filters.text], bio)]
140+
},
141+
142+
fallbacks=[CommandHandler('cancel', cancel)]
143+
)
144+
145+
dp.add_handler(conv_handler)
146+
147+
# log all errors
148+
dp.add_error_handler(error)
149+
150+
# Start the Bot
151+
updater.start_polling()
152+
153+
# Run the bot until the you presses Ctrl-C or the process receives SIGINT,
154+
# SIGTERM or SIGABRT. This should be used most of the time, since
155+
# start_polling() is non-blocking and will stop the bot gracefully.
156+
updater.idle()
157+
158+
159+
if __name__ == '__main__':
160+
main()

telegram/ext/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@
3131
from .stringcommandhandler import StringCommandHandler
3232
from .stringregexhandler import StringRegexHandler
3333
from .typehandler import TypeHandler
34+
from .conversationhandler import ConversationHandler
3435

3536
__all__ = ('Dispatcher', 'JobQueue', 'Job', 'Updater', 'CallbackQueryHandler',
3637
'ChosenInlineResultHandler', 'CommandHandler', 'Handler', 'InlineQueryHandler',
3738
'MessageHandler', 'Filters', 'RegexHandler', 'StringCommandHandler',
38-
'StringRegexHandler', 'TypeHandler')
39+
'StringRegexHandler', 'TypeHandler', 'ConversationHandler')

telegram/ext/callbackqueryhandler.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def check_update(self, update):
5252
def handle_update(self, update, dispatcher):
5353
optional_args = self.collect_optional_args(dispatcher)
5454

55-
self.callback(dispatcher.bot, update, **optional_args)
55+
return self.callback(dispatcher.bot, update, **optional_args)
5656

5757
# old non-PEP8 Handler methods
5858
m = "telegram.CallbackQueryHandler."

telegram/ext/choseninlineresulthandler.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def check_update(self, update):
5353
def handle_update(self, update, dispatcher):
5454
optional_args = self.collect_optional_args(dispatcher)
5555

56-
self.callback(dispatcher.bot, update, **optional_args)
56+
return self.callback(dispatcher.bot, update, **optional_args)
5757

5858
# old non-PEP8 Handler methods
5959
m = "telegram.ChosenInlineResultHandler."

telegram/ext/commandhandler.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ def handle_update(self, update, dispatcher):
8383
if self.pass_args:
8484
optional_args['args'] = message.text.split(' ')[1:]
8585

86-
self.callback(dispatcher.bot, update, **optional_args)
86+
return self.callback(dispatcher.bot, update, **optional_args)
8787

8888
# old non-PEP8 Handler methods
8989
m = "telegram.CommandHandler."

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy